4

I currently have the command \aeq{} to easily print the equivalents used in a chemical reaction in my experimental section. I use numbers rounded to one decimal place.

However, in some reactions, I need to have numbers smaller than 0.1 and I would like to have \aeq{} do the following: multiply by 100 and print the result followed by mol-%.

\documentclass{scrbook} 

\usepackage{chemmacros} % this loads xparse, which supplies \NewDocumentCommand{func}{argspec}{code}

\NewDocumentCommand{\aeq}{m}{#1~eq.} % equivalents

\begin{document}
\aeq{2.5} % prints 2.5~eq.

\aeq{0.03} % prints 0.03~eq., but I want to have it print 3~mol-%
\end{document}

3 Answers 3

4

You can use the floating point module of expl3 (loaded along with xparse):

\documentclass{scrbook}

\usepackage{chemmacros} % this loads xparse, which supplies \NewDocumentCommand{func}{argspec}{code}

\ExplSyntaxOn

\NewDocumentCommand{\aeq}{m}
 {
  \fp_compare:nTF { #1 < 1 }
   {
    \fp_eval:n { #1 * 100 }\nobreakspace\textnormal{mol-\%}
   }
   {
    #1\nobreakspace eq\@.
   }
 }

\ExplSyntaxOff

\begin{document}

\aeq{2.5} % prints 2.5~eq.

\aeq{0.03} % prints 3~mol-%

\end{document}

enter image description here

3
  • I was very happy when I got to my answer. But this is so much more elegant and spares me the loading of two packages!
    – basseur
    Oct 18, 2017 at 14:26
  • One more thing, though: I am actually using the acronyms package and have one acronym defined as eq.. I would need to call \acs{eq.} in this macro, which of course does not work here as \acs{eq\@.} How can I add this?
    – basseur
    Oct 18, 2017 at 14:36
  • 1
    @basseur Probably \@ is not needed in that context. However, if you're using \frenchspacing it's irrelevant if you add \@ or not.
    – egreg
    Oct 18, 2017 at 14:43
2

This compound \def will work.

EDITED to handle integer arguments as well as indefinite number of decimal places.

\documentclass{scrbook} 
\usepackage{chemmacros} % this loads xparse, which supplies \NewDocumentCommand{func}{argspec}{code}

\makeatletter
\newcommand\aeq[1]{\aeqaux#1\relax.\relax.\aeqauxend}
\def\aeqaux#1.#2#3.\aeqauxend{%
  \ifx\relax#2#1~eq.\else
    \expandafter\ifx\expandafter\relax\@firstoftwo#3#1.#2~eq.\else\aeqauxaux#3~mol-\%\fi%
  \fi%
}
\def\aeqauxaux#1#2.{#1\ifx#2\relax\else.#2\fi}
\makeatother

\begin{document}
\aeq{12}\par
\aeq{5}\par
\aeq{3.}\par
\aeq{2.5}\par
\aeq{0.3}\par
\aeq{0.03}\par
\aeq{0.003}\par
\aeq{0.0003}\par
\aeq{0.00023}
\end{document}

enter image description here

2
  • Also a very nice solution. But I chose egregs version, as it was easier for me to follow the steps in the macro.
    – basseur
    Oct 18, 2017 at 15:11
  • 1
    @basseur You and me both, LOL! Oct 18, 2017 at 15:17
0

While writing the question I did some digging and came to the following solution using calculator and ifthen.

\documentclass{scrbook} 

\usepackage{xparse}
\usepackage{calculator}
\usepackage{ifthen}

\NewDocumentCommand{\aeq}{m}{%
    \ifthenelse{\lengthtest{#1pt > 0.1pt}}{#1~eq.}{%
        \MULTIPLY{#1}{100}{\myaeq} % multiply #1 by 100 and store into \myaeq
        \ROUND[0]{\myaeq}{\myaeq} % round \myaeq to 0 decimal places, because \multiply does weird calculations
        \myaeq~mol-\%% print result
    }%
} % equivalents

\begin{document}
\aeq{2.5} % prints 2.5~eq

\aeq{0.03} % prints 3~mol-\%

\aeq{0.9} % prints 0.9~eq

\aeq{0.1} % prints 10~mol-\%
\end{document}

This will give you

enter image description here

As you can see, everything bigger than 0.1 gets printed as is followed by ~eq., while 0.1 and smaller is multiplied by 100, rounded to 0 decimal places and printed with ~mol-%* appended.

Notice: You have to do the test as a \lengthtest because \ifthenelse does not work with float-point values and for \lengthtest you need to append pt to not get an error. Also: % behind parentheses and \% are needed to prevent unwanted spaces after and before the macro.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .