19

I'm reading five values from external CSV file as [\sone, \stwo, \sthree, \sfour, \sfive]. Sample values could be [55.3, 89.0, 33.5, 40, 0.10].

Question :

  1. How to compare number with decimal points. For example, I can compare numbers using \ifnum\sone=1, but it does not accept decimal point.

  2. How to apply logical OR condition for printing respective statements? For example,

    IF \sone > 70.4 OR \stwo > 80.33 OR \sthree <= 33.0 OR \sfour = 80 OR \sfive >= 0.11 THEN
    Print this line
    ELSE Print other line
    END IF

17

The "traditional" way is the old-school way. That is, you convert the numbers into lengths/dimensions (that can contain decimal values, like 2.5pt) and perform the comparison using \ifdim rather than \ifnum.

Logical operations like OR and AND are performed using the basic \if...<true>\else<false>\fi structure, mixing and match as required to obtain the required output. For example, logical OR could be

\if...<true>\else\if...<true>\fi\fi

while logical AND could be

\if...\if...<true>\fi\fi

Here is an example that addresses your question:

enter image description here

\documentclass{article}
\def\sone{55.3}
\def\stwo{89.0}
\def\sthree{33.5}
\def\sfour{40}
\def\sfive{0.10}
\begin{document}

two \ifdim\stwo pt<\sthree pt $<$\else $\geq$\fi{} three \par
five \ifdim\sfive pt<\sfour pt $<$\else $\geq$\fi{} four \par

\newif\ifcondition\conditionfalse

\ifdim\sone pt>70.4pt A\conditiontrue\else
\ifdim\stwo pt>80.33pt B\conditiontrue\else
\ifdim\sthree pt<33.0pt C\conditiontrue\else
\ifdim\sthree pt=33.0pt D\conditiontrue\else
\ifdim\sfour pt=80pt E\conditiontrue\else
\ifdim\sfive pt>0.11pt F\conditiontrue\else
\ifdim\sfive pt=0.11pt G\conditiontrue%\else
\fi\fi\fi\fi\fi\fi\fi

\ifcondition thisline\else otherline\fi

\end{document}

To avoid great duplication in the last clause, I've created a boolean \ifcondition and set it to true - \conditiontrue - if any one of the cases are met. Otherwise it remains false - \conditionfalse. I've additionally included where the condition is met with the nested string of conditionals.


etoolbox "simplifies" this input greatly with the ability to mix logical operators as needed using \ifboolexpr{<expression>}{<true>}{<false>}. The above MWE is replicated using the etoolbox boolean expression syntax below:

enter image description here

\documentclass{article}
\usepackage{etoolbox}% http://ctan.org/pkg/etoolbox
\def\sone{55.3}
\def\stwo{89.0}
\def\sthree{33.5}
\def\sfour{40.0}
\def\sfive{0.1}
\begin{document}

two
\ifboolexpr{
  test {\ifdimless{\stwo pt}{\sthree pt}}
}
{$<$} % true
{$\geq$} % false
three

five
\ifboolexpr{
  test {\ifdimless{\sfive pt}{\sfour pt}}
}
{$<$} % true
{$\geq$} % false
four

\ifboolexpr{
  test {\ifdimgreater{\sone pt}{70.4pt}} or
  test {\ifdimgreater{\stwo pt}{80.33pt}} or
  (test {\ifdimless{\sthree pt}{33.0pt}} or test {\ifdimequal{\sthree pt}{33.0pt}}) or
  test {\ifdimequal{\sfour pt}{80pt}} or
  (test {\ifdimgreater{\sfive pt}{0.11pt}} or test {\ifdimequal{\sfive pt}{0.11pt}})
}
{thisline} % true
{otherline} % false

\end{document}

test {<bool expression>} is used to evaluate any boolean expression other than the basic TeX \if-conditionals, and grouping/nesting is allowed. Read more about these tests in sections 3.6.4 Arithmetic Tests and 3.6.5 Boolean Expressions (p 18-23) of the etoolbox documentation.

etoolbox, by the way, should be in every LaTeX-user's toolkit.


If your numbers all have the same structure, say XXX.XX, then you can also use pdfTeX's \pdfstrcmp{<string1>}{<string2>}. This command compares two strings and expands to 0 if the strings are equal (<string1> = <string2>), to -1 if the first string ranks before the second (<string1> < <string2>), and to 1 otherwise (<string1> > <string2>). The primitive was introduced in pdfTEX 1.30.0.

enter image description here

\documentclass{article}
\def\sone{55.3}
\def\stwo{89.0}
\def\sthree{33.5}
\def\sfour{40.0}
\def\sfive{00.1}
\begin{document}

\ifnum\pdfstrcmp{\stwo}{\sthree}=-1 two $<$ three \else two $\geq$ three\fi \par
\ifnum\pdfstrcmp{\sfive}{\sfour}=-1 five $<$ four \else five $\geq$ four\fi \par

\end{document}
  • Thanks a lot Sir. I've learnt a lot from your post. Now, I'm able to compare required numbers. – Pawan Mude Oct 5 '13 at 4:19
  • Quote: logical OR could be \if...<true>\else\if...<true>\fi\fi end quote. You see, the <true> part has to be written twice. Is it possilbe to write <true> part only once in logical OR with Tex primitives like it does in logical AND you give? – lyl Feb 27 at 10:34
8

One can use l3fp facilities:

\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\DeclareExpandableDocumentCommand{\booltest}{mmm}
 {
  \bool_if:nTF { #1 } { #2 } { #3 }
 }
\DeclareExpandableDocumentCommand{\fpcompare}{m}
 {
  \fp_compare_p:n { #1 }
 }
\ExplSyntaxOff

\begin{document}

\def\sone{55.3}
\def\stwo{89.0}
\def\sthree{33.5}
\def\sfour{40}
\def\sfive{0.10}

\booltest{
  \fpcompare{\sone > 0.74} || 
  \fpcompare{\stwo > 80.33} ||
  \fpcompare{\sthree <= 33.0} ||
  \fpcompare{\sfour = 80} ||
  \fpcompare{\sfive >= 0.11}
 }
 {Print this line}
 {Print this other line}

\def\sone{0.73}
\def\stwo{80}
\booltest{
  \fpcompare{\sone > 0.74} || 
  \fpcompare{\stwo > 80.33} ||
  \fpcompare{\sthree <= 33.0} ||
  \fpcompare{\sfour = 80} ||
  \fpcompare{\sfive >= 0.11}
 }
 {Print this line}
 {Print this other line}

\end{document}

This outputs

Print this line
Print this other line

One can also use parentheses around subexpressions, the negation operator ! and the and operator &&.

  • I would gladly upvote, but that would break the current draw in upvotes to your advantage ... ;-) – user4686 Oct 5 '13 at 13:55
  • my count moved up, so I did upvote l3fp... can't do anything more now ;-) – user4686 Oct 5 '13 at 13:59
  • @jfbu Now it's not a draw, as I upvoted yours. – egreg Oct 5 '13 at 13:59
  • molto bravo! grazie. – user4686 Oct 5 '13 at 14:00
8

You can compare numerical quantities (with decimal points, scientific notation or fractions) and combine numerical conditions using xintfrac, and, for easier input syntax xintexpr.

Updated as xintexpr has been expanded since original answer.

\documentclass{article}
\usepackage{xintexpr}% version 1.1 or later.

\begin{document}
\def\sone{55.3}
\def\stwo{89.0}
\def\sthree{33.5}
\def\sfour{40}
\def\sfive{0.10}


\xintifboolexpr {  \sone > 70.4  ||  \stwo > 80.33 || \sthree <= 33.0 || 
                     \sfour = 80 || \sfive >= 0.11 }
         {At least one of the inequalities is true}
         {None of the tested inequalities is true}

% Alternative syntax:

\xintifboolexpr {  \sone > 70.4  'or'  \stwo > 80.33 'or' \sthree <= 33.0 'or' 
                     \sfour = 80 'or' \sfive >= 0.11 }
         {At least one of the inequalities is true}
         {None of the tested inequalities is true}

\xintifboolexpr {any(\sone > 70.4, \stwo > 80.33 , \sthree <= 33.0,
                          \sfour = 80, \sfive >= 0.11)}
         {At least one of the inequalities is true}
         {None of the tested inequalities is true}

\xintifboolexpr { 3.5 > 3.4 'and' (-123 > -123.1 'or' -123 > -122.9) }
             {YES}
             {NO}

% equivalently

\xintifboolexpr { 3.5 > 3.4 && (-123 > -123.1 || -123 > -122.9)}
             {YES}
             {NO}

\end{document}

booleans

1

If you already use TikZ (3.0.0+) you can use math library. But do not load TikZ just for this, the other answers are (probably) lighter and faster than this one.

\documentclass[varwidth,border=50]{standalone}
\usepackage{tikz}
\usetikzlibrary{math}

\begin{document}
% define all constants
\def\sone{55.3}
\def\stwo{89.0}
\def\sthree{33.5}
\def\sfour{40}
\def\sfive{0.10}
% make a decision
\tikzmath{
  int \answer;
  if ( \sone > 70.4  ||  \stwo < 80.33 || \sthree*\sfive <= \sfour-35 ) then {
    \answer = 43*sin(\stwo);
    {The third inequality is true, so ...\newline};
  } else {
    \answer = 0;
    {This will not be printed.};
  };
}
% Output the result
the Answer to the Ultimate Question of Life, the Universe, and Everything is: \answer
\end{document}

enter image description here

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.