![嵌套 FPifeq :额外的 \fi 错误](https://linux22.com/image/399502/%E5%B5%8C%E5%A5%97%20FPifeq%20%EF%BC%9A%E9%A2%9D%E5%A4%96%E7%9A%84%20%5Cfi%20%E9%94%99%E8%AF%AF.png)
我想要一个带有 1 个参数的命令单元并返回:
- 如果参数为 1,则不执行任何操作
-
如果参数为 -1- 任何其他情况下的参数
目标是展示X和 -X而不是我随机生成的练习中的 1*x* 和 -1*x*。
这是我发出的命令:
\newcommand\Unit[1]{\FPifeq#1{1}{}\else\FPifeq#1{-1}{-}\else#1\fi\fi}
但是,它会产生以下错误
Extra \fi
最小示例:
\documentclass[a4paper]{article}
\usepackage[utf8]{inputenc}
\usepackage[french]{babel}
\usepackage[T1]{fontenc}
\usepackage{geometry}
\geometry{hmargin=1cm,vmargin=1cm}
\usepackage{amsmath}
\usepackage{amssymb}
\usepackage{fp}
\begin{document}
\newcommand\Unit[1]{\FPifeq#1{1}{}\else\FPifeq#1{-1}{-}\else#1\fi\fi}
\Unit{2}x \Unit{1}x \Unit{-1}x
\end{document}
答案1
宏\FPifeq
不喜欢嵌套在条件中,因为它不是条件句。其结构基本上是
- 进行一些比较,最终有助于决定是否执行
\FP@testtrue
或\FP@testfalse
,使其\ifFP@test
等于\iftrue
或\iffalse
; - 设为
\ifFPtest
等于\ifFP@test
; \ifFPtest
在输入流中释放。
然而,TeX 并不将其识别\FPifeq
为条件,因此使用你的宏
\FPifeq#1{1}{}\else\FPifeq#1{-1}{-}\else#1\fi\fi
发生以下情况
当
#1
是时1
,然后\ifFPtest
是\iftrue
,我们最终得到\iftrue{}\else\FPifeq#1{-1}{-}\else#1\fi\fi
现在
{}
会留在输入流中,\else
会删除匹配 之前的所有内容\fi
。哦,不!还有\fi
剩余!当
#1
不是时1
,则\ifFPtest
是\iffalse
,最后我们得到\iffalse{}\else\FPifeq#1{-1}{-}\else#1\fi\fi
现在一切都
\else
被移除了,我们仍然\FPifeq#1{-1}{-}\else#1\fi\fi
但 TeX 会记得它已经删除了
\else
。然后一切都会正常进行,因为在作业的末尾,或\FPifeq
都会产生结果。尾随对应于预先删除的 ,因此不会造成损害。\iftrue
\iffalse
\fi
\else
您的代码中存在一些小问题:它应该贯穿{#1}
始终,否则诸如12
将1
作为第一个参数的值\FPifeq
作为2
第二个参数。
你可以修复嵌套问题
\newcommand{\FPeq}{TT\fi\FPifeq}
\newcommand\Unit[1]{%
\if\FPeq{#1}{1}%
% do nothing
\else
\if\FPeq{#1}{-1}%
-%
\else
#1%
\fi
\fi
}
这是一个老把戏,用来\if
使上述问题消失;如果\if
展开,它会看到TT\fi
,这会导致真实测试并将\FPifeq
被执行;如果它在跳过的文本中,它将正确匹配相应的\else
或\fi
。
但是,使用\FPifeq
会对最终的输出产生不良影响。让我们看一个例子:
\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}
你能看出问题所在吗? 的工作\FPifeq
会创建一个空的数学原子,因此如果多项式是前导数,则减号将被视为二元运算符,而不是一元运算符。
使用 Phelype Oleinik 的代码时,问题并未显现expl3
。
答案2
你不需要这样做fp
。TeX 可以使用 进行整数比较\ifnum
。这:
\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}
生产2x x -x
。
如果要使用fp
,则需要在另一个宏中隐藏第二个测试。显然fp
不喜欢嵌套条件:
\newcommand\Unit[1]{%
\FPifeq{#1}{1}%
% nothing
\else
\UnitInner{#1}%
\fi}
\newcommand\UnitInner[1]{%
\FPifeq{#1}{-1}%
-%
\else
#1%
\fi}
但是,我建议您使用expl3
它自己的 FPU。它更加灵活,并允许您轻松编写嵌套条件:
\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}