Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

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.

share|improve this question
add comment

5 Answers

up vote 5 down vote accepted

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}
share|improve this answer
    
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
show 2 more comments

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}
share|improve this answer
add comment
\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}
share|improve this answer
    
+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 :-) –  Herbert 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
add comment

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}
share|improve this answer
    
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
add comment

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}
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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