18

Example:

\usepackage{siunitx}

\newcommand{\temperature}[1]{\SI{#1}{\celsius}}
\temperature{100}

output: 100°C

I would like something like:

\newcommand{\temperature}[1]{\SI{#1+273}{\kelvin} (\SI{#1}{\celsius})}
\temperature{100}

output: 373K (100°C)

Is it possible?

Mico
  • 506,678
bryebex
  • 181

4 Answers4

15

You can use the l3fp module of expl3:

\documentclass{article}
\usepackage{siunitx} % already loads xparse

\ExplSyntaxOn
\NewDocumentCommand{\temperature}{ O{0} m }
 {
  \bryebex_temperature:nn { #1 } { #2 }
 }

\cs_new_protected:Npn \bryebex_temperature:nn #1 #2
 {
  \SI{ \fp_to_decimal:n { round ( #2+273.15, #1 ) } } { \kelvin }
  \nobreakspace ( \SI { #2 } { \celsius } )
 }
\ExplSyntaxOff

\begin{document}

\temperature{100}

\temperature[2]{100}

\end{document}

The optional argument tells the number of decimal digits for the rounding.

enter image description here

egreg
  • 1,121,712
  • 5
    Note that it's likely that I'll extend siunitx to have this ability available 'natively' for the next major release. I'm hoping to work on it over the Christmas holidays. – Joseph Wright Nov 22 '13 at 16:06
  • @JosephWright Exactly what ability? Doing automatic calculations? – Svend Tveskæg Nov 22 '13 at 16:36
  • 2
    @SvendTveskæg Treating the numerical input as a floating-point expression. Current thinking is to make this optional with the result having to be a simple real number. I need to extend the parser approach in several ways as it is. – Joseph Wright Nov 22 '13 at 16:38
  • @JosephWright Thank you for the explanation. – Svend Tveskæg Nov 22 '13 at 16:42
  • @JosephWright I first tried with \exp_args:Nx in front of the first \SI, but then I realized it's not needed as \SI already does full expansion on its first argument. – egreg Nov 22 '13 at 16:47
7

You can calculate the expression #1+273 outside \SI and use it. To calculate you can use your preferred method. I chose pgf.

\documentclass{article}
\usepackage{siunitx,pgf}
\newcommand*{\temperature}[1]{\pgfmathtruncatemacro{\temp}{#1+273}\SI{\temp}{\kelvin} (\SI{#1}{\celsius})}
%no truncation
\newcommand*{\temperatur}[1]{\pgfmathparse{#1+273}\SI{\pgfmathresult}{\kelvin} (\SI{#1}{\celsius})}
%
\begin{document}
    \temperatur{100.23} and \temperature{123}
\end{document}

enter image description here

5

To each his/her favourite math engine...

Blockquote

Update: using \xinttheexpr...\relax for infix notations. But it doesn't seem that \SI does a full expansion immediately, it first apparently parses for ( and ) among others. So I had to do a little trick with a \firstofone.

\documentclass{article}
\usepackage{siunitx,xintexpr}

\providecommand\firstofone [1]{#1}

% We use this \firstofone trick to hide ( and ) from the \SI parser.
% Braces can not be used inside \xinttheexpr...\relax for this purpose

\newcommand*{\celsiusfromkelvin}[2][2]
     {\SI{\firstofone {\xinttheexpr round(#2-273.15,#1)\relax}}{\celsius}}
\newcommand*{\celsiusfromfahrenheit}[2][2]
     {\SI{\firstofone {\xinttheexpr round((#2-32)*5/9,#1)\relax}}{\celsius}}
\newcommand*{\fahrenheitfromkelvin}[2][2]
     {\SI{\firstofone {\xinttheexpr round(1.8*#2-459.67,#1)\relax}}{\fahrenheit}}
\newcommand*{\fahrenheitfromcelsius}[2][2]
     {\SI{\firstofone {\xinttheexpr round(1.8*#2+32,#1)\relax}}{\fahrenheit}}
\newcommand*{\kelvinfromcelsius}[2][2]
     {\SI{\firstofone {\xinttheexpr round(#2+273.15,#1)\relax}}{\kelvin}}
\newcommand*{\kelvinfromfahrenheit}[2][2]
     {\SI{\firstofone {\xinttheexpr round((#2+459.67)*5/9,#1)\relax}}{\kelvin}}



\DeclareSIUnit[number-unit-product=\,]
\fahrenheit{\SIUnitSymbolDegree F}    
\begin{document}
    \celsiusfromkelvin {300} (\SI{300}{\kelvin})

    \fahrenheitfromkelvin {300} (\SI{300}{\kelvin})

    \celsiusfromfahrenheit {80.33} (\SI{80.33}{\fahrenheit})

    \fahrenheitfromcelsius {26.85}  (\SI{26.85}{\celsius})

    \kelvinfromcelsius {26.85} (\SI{26.85}{\celsius})

    \kelvinfromfahrenheit {80.33} (\SI{80.33}{\fahrenheit})

    \celsiusfromfahrenheit [4] {80} (\SI{80}{\fahrenheit})

    \fahrenheitfromcelsius [4] {26.6667}  (\SI{26.6667}{\celsius})

    \fahrenheitfromcelsius [4] {26.66667}  (\SI{26.66667}{\celsius})


\end{document}

Earlier method, without infix notations

\documentclass{article}
\usepackage{siunitx,xintfrac}

\newcommand*{\celsiusfromkelvin}[2][2]
     {\SI{\xintRound{#1}{\xintSub{#2}{273.15}}}{\celsius}}
\newcommand*{\celsiusfromfahrenheit}[2][2]
     {\SI{\xintRound{#1}{\xintMul{\xintSub{#2}{32}}{5/9}}}{\celsius}}
\newcommand*{\fahrenheitfromkelvin}[2][2]
     {\SI{\xintRound{#1}{\xintSub{\xintMul{#2}{1.8}}{459.67}}}{\fahrenheit}}
\newcommand*{\fahrenheitfromcelsius}[2][2]
     {\SI{\xintRound{#1}{\xintAdd{\xintMul{#2}{1.8}}{32}}}{\fahrenheit}}
\newcommand*{\kelvinfromcelsius}[2][2]
     {\SI{\xintRound{#1}{\xintAdd{#2}{273.15}}}{\kelvin}}
\newcommand*{\kelvinfromfahrenheit}[2][2]
     {\SI{\xintRound{#1}{\xintMul{\xintAdd{#2}{459.67}}{5/9}}}{\kelvin}}


\DeclareSIUnit[number-unit-product=\,]
\fahrenheit{\SIUnitSymbolDegree F}

\begin{document}

    \celsiusfromkelvin {300} (\SI{300}{\kelvin})

    \fahrenheitfromkelvin {300} (\SI{300}{\kelvin})

    \celsiusfromfahrenheit {80.33} (\SI{80.33}{\fahrenheit})

    \fahrenheitfromcelsius {26.85}  (\SI{26.85}{\celsius})

    \kelvinfromcelsius {26.85} (\SI{26.85}{\celsius})

    \kelvinfromfahrenheit {80.33} (\SI{80.33}{\fahrenheit})

    \celsiusfromfahrenheit [4] {80} (\SI{80}{\fahrenheit})

    \fahrenheitfromcelsius [4] {26.6667}  (\SI{26.6667}{\celsius})

    \fahrenheitfromcelsius [4] {26.66667}  (\SI{26.66667}{\celsius})


\end{document}
2

My first thought: With luaLaTeX it should be quite easy.

Here it is:

\documentclass{scrartcl} 
\usepackage{siunitx}
\newcommand{\temperature}[1]{\SI{\directlua{tex.sprint(#1+273.15)}}{\kelvin} (\SI{#1}{\celsius})}

\begin{document}
\temperature{100}
\end{document}

I replaced your #1+273 with \directlua{tex.sprint(#1+273.15)}.

knut
  • 8,838