# How can I convert units in LaTeX environment?

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?

• Welcome to TeX.SE! A quick hint: If you indent lines of LaTeX code by four spaces, they will be auto-formatted appropriately.
– Mico
Nov 22 '13 at 14:08
• In addition to the great answers below, you can have a look on an fp-package solution in this answer: tex.stackexchange.com/a/87825 Nov 22 '13 at 14:53
• Remember that the difference is 275.15 degrees, not 273 degrees. Nov 22 '13 at 15:15
• @SvendTveskæg I thought you couldn't have temperatures lower than 0 K, but with your suggested transformation we can go down to -2K. Nov 22 '13 at 19:02
• No it cannot; absolut zero is 0 degrees Kelvin and that is equivalent to -273.15 degrees Celsius. Nov 23 '13 at 10:45

You can use the l3fp module of expl3:

\documentclass{article}

\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.

• 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. Nov 22 '13 at 16:06
• @JosephWright Exactly what ability? Doing automatic calculations? Nov 22 '13 at 16:36
• @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. Nov 22 '13 at 16:38
• @JosephWright Thank you for the explanation. 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. Nov 22 '13 at 16:47

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}


To each his/her favourite math engine...

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]
\newcommand*{\kelvinfromcelsius}[2][2]
\newcommand*{\kelvinfromfahrenheit}[2][2]

\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}


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)}.