Nested FPifeq : Extra \fi error

You don't need fp for that. TeX can do integer comparison with \ifnum. This:

\documentclass{article}
\newcommand\Unit[1]{%
  \ifnum#1=1
    % nothing
  \else
    \ifnum#1=-1
      -%
    \else
      #1%
    \fi
  \fi}
\begin{document}
\Unit{2}x \Unit{1}x \Unit{-1}x
\end{document}

produces 2x x -x.


If you want to use fp, then you need to hide the second test in another macro. Apparently fp doesn't like nested conditionals:

\newcommand\Unit[1]{%
  \FPifeq{#1}{1}%
    % nothing
  \else
    \UnitInner{#1}%
  \fi}
\newcommand\UnitInner[1]{%
  \FPifeq{#1}{-1}%
    -%
  \else
    #1%
  \fi}

However, I recommend you use expl3 and it's own FPU. It's much more flexible and allows you to easily compose nested conditionals:

\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewExpandableDocumentCommand \Unit { m }
  {
    \fp_compare:nF { #1 == 1 }
      {
        \fp_compare:nTF { #1 == -1 }
          { - }
          { #1 }
      }
  }
\ExplSyntaxOff
\begin{document}
\Unit{2}x \Unit{1}x \Unit{-1}x
\end{document}

The macro \FPifeq doesn't like to be nested in a conditional, because it is not a conditional. Its structure is basically

  • do some comparisons that eventually help to decide whether to execute \FP@testtrue or \FP@testfalse, which make \ifFP@test equal to either \iftrue or \iffalse;
  • set \ifFPtest equal to \ifFP@test;
  • release \ifFPtest in the input stream.

However, TeX does not recognize \FPifeq as a conditional, so with your macro

\FPifeq#1{1}{}\else\FPifeq#1{-1}{-}\else#1\fi\fi

the following happens

  • when #1 is 1, then \ifFPtest is \iftrue, and we end up with

    \iftrue{}\else\FPifeq#1{-1}{-}\else#1\fi\fi
    

    Now {} will be left in the input stream and the \else will remove everything up to the matching \fi. Oh, no! Another \fi remains!

  • when #1 is not 1, then \ifFPtest is \iffalse, and we end up with

    \iffalse{}\else\FPifeq#1{-1}{-}\else#1\fi\fi
    

    Now everything up to \else is removed and we remain with

    \FPifeq#1{-1}{-}\else#1\fi\fi
    

    but TeX remembers it has removed an \else. Then everything will work well, because at the end of the job of \FPifeq either \iftrue or \iffalse will result. The trailing \fi corresponds to the \else removed in advance, so it doesn't harm.

There are a few glitches in your code: it should be {#1} throughout, otherwise a value such as 12 would take 1 as the first argument to \FPifeq and 2 as the second argument.

You could fix the nesting problem by doing

\newcommand{\FPeq}{TT\fi\FPifeq}
\newcommand\Unit[1]{%
  \if\FPeq{#1}{1}%
    % do nothing
  \else
    \if\FPeq{#1}{-1}%
      -%
    \else
      #1%
    \fi
  \fi
}

This is an old trick that uses \if to make the problem above vanish; if \if is expanded, it sees TT\fi, which results in a true test and \FPifeq will be executed; if it is in skipped text, it will correctly match a corresponding \else or \fi.

However, the usage of \FPifeq has bad consequences on the final output. Let's see an example:

\documentclass{article}
\usepackage[nomessages]{fp}

\newcommand{\FPeq}{TT\fi\FPifeq}
\newcommand\Unit[1]{%
  \if\FPeq{#1}{1}%
    % do nothing
  \else
    \if\FPeq{#1}{-1}%
      -%
    \else
      #1%
    \fi
  \fi
}

\begin{document}

$\Unit{2}x$ $\Unit{1}x$ $\Unit{-1}x$

$2x$ $x$ $-x$

\end{document}

enter image description here

Can you see the problem? The working of \FPifeq creates an empty math atom, so the minus sign is treated as a binary operator rather than a unary, if leading the polynomial.

The problem does not show with Phelype Oleinik's code using expl3.