10

Is there an easy way to test if a number is negative?

I don't need a general solution, but it does need to be able to handle a floating point value. I was using this solution from tex.ac.uk until I realized that it has problems with positive floating point numbers. Here is a test file

\documentclass{article}

\def\IsPositive#1{%
  TT\fi%
  \ifcat_\ifnum0<0#1 _\else A\fi%
}

\newcommand{\PrintSignOfNumber}[1]{%
    \if\IsPositive{#1}%
        $#1 \ge 0$%
    \else%
        $#1 < 0$%
    \fi%
}

\begin{document}

\PrintSignOfNumber{2}\par 
\PrintSignOfNumber{-2}

\PrintSignOfNumber{2.0}\par  % reported as negative
\PrintSignOfNumber{-2.0}

\end{document}

I don't need a very general solution. Even if it just tested the first character as being a negative sign would suffice for my application. I would think that the etoolbox could do this easily, but I can't quite figure out how. If anyone knows of a good document that contains examples of using etoolbox that would be great.

6

If you are an adept of TikZ, the next solution is for you (with pgf 2.1)

\documentclass[]{scrartcl}
\usepackage{tikz}
\newcommand\test[1]{
\pgfmathsetmacro{\var}{#1}
\pgfmathparse{ifthenelse(\var>=0,"positif","négatif")} \pgfmathresult}%

\begin{document} 

\test{1}   \test{-2} \test{cos(95)}

\end{document}

Modified version :

\documentclass[]{scrartcl}
\usepackage{tikz}

\newcommand\ifPositif[3]{ 
\begingroup
\pgfmathsetmacro{\var}{#1}
\pgfmathparse{ifthenelse(\var>=0,1,0)} 
\ifdim\pgfmathresult pt= 1 pt 
   #2
  \else 
   #3
\fi 
\endgroup
}

\begin{document}

\ifPositif{1}{pos}{neg} 

\ifPositif{2-2}{\pgfmathparse{sqrt(3)} \pgfmathresult}
                {\pgfmathparse{sqrt(2)} \pgfmathresult} 

\ifPositif{cos(95)+sqrt(2)}{\pgfmathparse{sqrt(5)} \pgfmathresult}
                            {\pgfmathparse{sqrt(6)} \pgfmathresult}

\ifPositif{-1e-2}{pos}{neg}

\ifPositif{1-5e2}{\var}{\foreach \x in {1,2}{\x}} 

\ifPositif{1-5e2}{\var}{\var}   
\end{document}
  • All the solutions here work great. I like this the best as it is a lot more flexible, but I would prefer to have a wrapper macro so when I need to use this I can just say something like \ifPositive{}{do this}{else do this}. I'm going to try to attempt to do this, but I am still only at the hacker stage when it comes to TeX – Peter Grill Apr 8 '11 at 17:53
  • @Peter I add the wrapper macro. – Alain Matthes Apr 8 '11 at 19:08
  • Works great. Not sure I fully understand the comparison to "1 pt". – Peter Grill Apr 8 '11 at 19:27
  • @Peter you can use \if\pgfmathresult 1 \relax instead of \ifdim – Alain Matthes Apr 8 '11 at 19:42
  • Just a minor remark: zero is neither positive nor negative; you could modify your example codes so that 0 is not reported as positive. – Gonzalo Medina Apr 8 '11 at 23:11
7

An easy way is to use a simple macro and test if the number is less than zero.

\documentclass{article}
\begin{document}

\def\test#1{%
\expandafter\ifnum#1<0 isNegative \else isPositive\fi
}
\test{-23}

\test{23}
\end{document}

For decimal numbers, modify as:

\documentclass{article}
\usepackage{fp}
\begin{document}

\def\test#1{%
\expandafter\ifnum#1<0 isNegative \else isPositive\fi
}
\test{-23}

\test{23}

\def\testReal#1{%
\FPiflt{#1}{0} isNegative\else isPositive\fi 
}

\testReal{-23.789}
\end{document}
  • For your second solution (the one using fp) you could also use fp-basic's macros \FPifneg#1 ...\else...\fi, \FPifpos#1 ...\else...\fi, and \FPifzero#1...\else...\fi. Also, just a minor remark: zero is neither positive nor negative. – Gonzalo Medina Apr 8 '11 at 23:17
  • @Gonzalo thanks for the comments and yes the code should have a test for zero as well. – Yiannis Lazarides Apr 10 '11 at 21:33
7

You can use \@ifnextchar{<char>}{<true>}{<false>} to check if the next character (actually next token) is -. I would also recommend to not use some \if TT\fi trickery but use a if-macro which accepts the true and false branches as arguments.

Here the argument is unbraced by the first macro and placed behind \@ifnextchar which is normally the last element in a macro to read the next character after it. The rest of the argument is then removed by \remove@to@nnil which removes everything to \@nnil. All of these macros are from the LaTeX kernel.

\documentclass{article}

\makeatletter
\def\ifPositive#1{%
    \@ifnextchar{-}%
      {\expandafter\@secondoftwo\remove@to@nnil}%
      {\expandafter\@firstoftwo\remove@to@nnil}%
        #1\@nnil
}
\makeatother

\newcommand{\PrintSignOfNumber}[1]{%
    \ifPositive{#1}%
        {$#1 \ge 0$}%
        {$#1 < 0$}
}

\begin{document}

\PrintSignOfNumber{2}\par 
\PrintSignOfNumber{-2}

\PrintSignOfNumber{2.0}\par
\PrintSignOfNumber{-2.0}

\end{document}

Prints:

 2 >= 0
-2 < 0
2:0 >= 0
-2:0 < 0

If your really want if-switches then you can do it like follows. Just make sure that the macro definition isn't inside a conditionals, otherwise the \fi, \iftrue and \iffalse will confuse TeX.

\documentclass{article}

\makeatletter
\def\isPositive#1{%
    TT\fi
    \@ifnextchar{-}%
    {\expandafter\iffalse\remove@to@nnil}%
    {\expandafter\iftrue\remove@to@nnil}%
        #1\@nnil
}
\makeatother

\newcommand{\PrintSignOfNumber}[1]{%
    \if\isPositive{#1}%
        $#1 \ge 0$%
    \else
        $#1 < 0$
    \fi
}

\begin{document}

\PrintSignOfNumber{2}\par
\PrintSignOfNumber{-2}

\PrintSignOfNumber{2.0}\par
\PrintSignOfNumber{-2.0}

\end{document}
7
\documentclass{article}

\makeatletter
\newcommand\PrintSignOfNumber[1]{%
  \ifdim#1pt<\z@ $#1<0$\else$#1\ge0$\fi}
\makeatother

\begin{document}

\PrintSignOfNumber{2}\par 
\PrintSignOfNumber{-2}

\PrintSignOfNumber{2.0}\par 
\PrintSignOfNumber{-2.0}

\end{document}
  • +1 This would be the simplest way to go. However one drawback is that it will cause a TeX compile error if the argument is not a number (anything else than +/-, digits, .). This is of course a general problem, but other solutions would be simple wrong, not causing an error. Ok, sometimes an error is what you want. This points you directly to the wrong input. – Martin Scharrer Apr 8 '11 at 13:12
  • it is also simple to check whether I have a valid dimension or not ... And, by the way: my solution also works for 2,1 which will be friendly to us germans :-) – user2478 Apr 8 '11 at 13:34
  • Nice. I didn't know that TeX accepts a , as well. – Martin Scharrer Apr 8 '11 at 13:37
  • Actually, I don't consider that a drawback. Its much more preferable to get a compile error rather than silently do the wrong thing. – Peter Grill Apr 8 '11 at 17:50
  • Nice solution.. – Gonzalo Medina Apr 8 '11 at 21:02
1

This method works regardless of integer or real type argument

\documentclass{article}
\usepackage{stringstrings}
\newcommand\PrintSignOfNumber[1]{%
  \isnextbyte[q]{-}{#1}%
  \if T\theresult$#1 < 0$\else$#1 \ge 0$\fi%
}
\begin{document}
\PrintSignOfNumber{2}\par 
\PrintSignOfNumber{-2}\par
\PrintSignOfNumber{2.0}\par
\PrintSignOfNumber{-2.0}
\end{document}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.