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}