[Tex/LaTex] \def function with arithmetic macro

esamifp

I have been writing multiple equations to use for exam writing. I have made some new macros that display a positive sign in front of an expression for positive numbers and display no sign for negative numbers.

Here is an example of a simple version of my definitions:

\def\dsignaddmulti#1#2#3#4{
\newcount\tmp
\newcount\ymp
\tmp=#1
\ymp=#3
\multiply\tmp by #2
\multiply\ymp by #4
\advance\tmp by \ymp
\FPifneg{\the\tmp}\else+\fi
}

I am trying to construct the same definition to multiply four numbers. The definition works, but is displaying the number after the "sign", which I do not want.

Here is the non-working code:

\def\dsignmulti#1#2#3#4{
\newcount\tmp
\newcount\ymp
\tmp=#1
\ymp=#3
\multiply\tmp by #2
\multiply\ymp by #4
\multiply \tmp by \ymp
\FPifneg{\the\tmp} \else+\fi
}

Is there something that I am missing?

These are defined in my esami.sty file if that helps.

Sorry, I moved this from egreg's response:

@egreg: I think I should be more clear about how I am using the function. In the esami package, you can perform arithmetic on random numbers using the esempli function. However, when placed inside of an equation, if the result is negative, I would end up with a positive sign following by a negative sign.

For example:

\begin{equation*}  x\dsignmulti{\a}{\b}{\c}{\d}+\esempli{a*b+c*d}{1} \end{equation*} 

If a*b+c*d is negative, the result has a positive and then negative sign following x. The definition is supposed to display a positive sign for positive numbers and display nothing for negative numbers. That way, I don't have two signs in a row. This is what I would like to use in my equation:

\begin{equation*}  x\dsignmulti{\a}{\b}{\c}{\d}\esempli{a*b+c*d}{1} \end{equation*} 

However, your code here:

\newcommand{\dsignmulti}[4]{%
  \@tempcnta=\numexpr#1*#2+#3*#4\relax
  \ifnum\@tempcnta>\z@ +\fi\number\@tempcnta
}

solution outputs two numbers, when I only want to display the sign. Is there an easy way to change this?

I apologize if I were unclear earlier.

Best Answer

A basic error is, first of all, having \newcount in the definition of \dsignmulti: you are allocating two new counters at every usage of the macro.

The LaTeX kernel already provides counters for temporary usage, \@tempcnta and \@tempcntb; so a better definition would be

\newcommand{\dsignmulti}[4]{%
  \@tempcnta=#1\relax
  \@tempcntb=#3\relax
  \multiply\@tempcnta by #2\relax
  \multiply\@tempcntb by #4\relax
  \advance\@tempcnta by \@tempcntb
  \ifnum\@tempcnta>\z@ +\fi\number\@tempcnta
}

A possibly easier way would be using directly the \numexpr functionality:

\newcommand{\dsignmulti}[4]{%
  \@tempcnta=\numexpr#1*#2+#3*#4\relax
  \ifnum\@tempcnta>\z@ +\fi\number\@tempcnta
}

You can even make it expandable, at the expense of speed:

\newcommand{\dsignmulti}[4]{%
  \ifnum\numexpr#1*#2+#3*#4\relax>\z@ +\fi
  \number\numexpr#1*#2+#3*#4\relax
}
Related Question