Floating point calculations in LaTeX?

If you don't mind using luatex, then you could just let lua do the calculations. I use ConTeXt, but I believe that the luacode package in LaTeX provides similar functionality.

\startusercode
  round = global.math.round 
\stopusercode

\def\bind#1#2%
    {\usercode{#1 = #2}\use{#1}}

\def\use#1%
    {\usercode{global.context(#1)}}

\starttext
 The experiment included running a battery of \bind{T}{21.0} tests
 on \bind{S}{13} subjects, for a total of \bind{V}{T*S} expected values.
 However, since \bind{F}{37} values were defective, our successful 
 measurement rate per subject was \use{100*round((V-F)/T,2)}\%
\stoptext

I am using usercode rather luacode so that my definitions (T=21 etc) do not pollute the global namespace.

EDIT: If you want the result to be in math mode, change global.context(...) to global.context.math(...) in the definition of \use


Another package to do floating point computations is l3fp. This package does not (yet) allow users to define new variables (but it supports pi, for instance, so in principle it shouldn't be too hard to extend it to support user-defined variables). A workaround is to go through the expression and replace all variables T, V, etc. by an internal variable \l__my_T_fp, \l__my_V_fp, etc., which holds the corresponding value.

This is done by the looping macro \__my_use:N, which reads one character at a time. If it is the end-marker \q_recursion_tail, then we reached the end of the expression, so exit the loop by skipping to \q_recursion_stop (done by \quark_if_recursion_tail_stop:n). If the variable \l__my_#1_fp is defined, then use it, otherwise leave the character itself for the l3fp functions to receive. Then recurse by calling \__my_use:N again.

The \my_set:nn function makes sure that \l__my_#1_fp is defined thanks to \fp_zero_new:c, then it sets its value.

\documentclass{article}
\usepackage{expl3, xparse}
\ExplSyntaxOn
\cs_new:Npn \__my_use:N #1
  {
    \quark_if_recursion_tail_stop:n {#1}
    \cs_if_exist_use:cF { l__my_#1_fp } {#1}
    \__my_use:N
  }
\cs_new:Npn \my_use:n #1
  { \fp_eval:n { \__my_use:N #1 \q_recursion_tail \q_recursion_stop } }
\cs_new_protected:Npn \my_set:nn #1#2
  {
    \fp_zero_new:c { l__my_#1_fp }
    \fp_set:cn { l__my_#1_fp } { \my_use:n {#2} }
  }
\NewDocumentCommand {\bind} { m m } { \my_set:nn {#1} {#2} \my_use:n {#1} }
\NewDocumentCommand {\use} { m } { \my_use:n {#1} }
\ExplSyntaxOff
\begin{document}
 The experiment included running a battery of \bind{T}{21} tests
 on \bind{S}{13} subjects, for a total of \bind{V}{T*S} expected values.
 However, since \bind{F}{37} values were defective, our successful
 measurement rate per subject was \use{100*round((V-F)/V,2)}\%
\end{document}

I also fixed the last formula, which read (V-F)/T.


I have been extensively using the fp for this type of work. Here is a minimal for some functions, that can convert temperature units from one system to another. There are a lot of examples on this site that use the fp package. The code uses the siunitx package for formatting as well.

For example to translate degrees F to C you type \Ftoc{32.999}. Here is a minimal example.

\documentclass{article}
\usepackage{fp}
\usepackage{siunitx}
\gdef\numdec{3}

\begin{document}
%\SetConversion{C}{K}{273.15}
\def\CtoK#1{\FPadd\result{#1}{273.15}%
\FPround\result{\result}{2}%
\sisetup{%
fixed-exponent = 2,
scientific-notation = false}
 \num{\result}}


%% Convert Centigrate to Fahreneit
\def\CtoF#1{\FPdiv\resulta{9}{5}%
\FPmul\resultb{\resulta}{#1}%
\FPadd\resultc{\resultb}{32}%
\FPround\resultc{\resultc}{3}%
 \num{\resultc}%
\sisetup{%
fixed-exponent = 0,
scientific-notation = false}
}

%% Convert Fahreneit to Centigrade
\def\FtoC#1{\FPdiv\resulta{5}{9}%
\FPsub\resultb{#1}{32}%
\FPmul\resultc{\resultb}{\resulta}%
\FPround\resultc{\resultc}{\numdec}%
\sisetup{%
fixed-exponent = 0,
scientific-notation = false}
\num{\resultc}%
}

%% Convert Fahreneit to Rankine
\def\FtoRa#1{\FPmul\result{#1}{9}%
\FPdiv\result{\result}{5}%
\FPround\result{\result}{\numdec}%
\result%
}

%% Convert Kelvin to Rankine
\def\KtoRa#1{\FPadd\result{#1}{459.67}%
\FPround\result{\result}{\numdec}\result}

%% Convert Rankine to Celcius
\def\RtoC#1{\FPsub\result{#1}{459.67}% to fahreneit
\FtoC{\result}}


\FtoC{32.999}

\end{document}

Tags:

Calculations