在我的文档中,我需要做一些与图像大小相关的数学运算。具体来说,我需要一个线性插值函数、线性插值的逆函数和一个钳位函数。
我已经构建了这些函数以及一个用于测试它们的文档:
\documentclass[twoside]{memoir}
\usepackage[papersize={8.5in,11in}, vmargin=0.5in, outer=1in, inner=0.5in, includehead, includefoot]{geometry}
\usepackage{fp}
\makeatletter
\newcommand\clamp[3] {
\def\clamped{#1}
\ifdim #1pt>#3pt
\def\clamped{#3}
\fi
\ifdim #1pt<#2pt
\def\clamped{#2}
\fi
\clamped
}
\newcommand\unlerp[3] {
\FPsub\numerator{\number #1}{\number #2}
\FPsub\denominator{\number #3}{\number #2}
\FPdiv\result{\numerator}{\denominator}
\result
}
\newcommand\lerp[3] {
\FPsub\result{\number #3}{\number #2}
\FPmul\result{\number #1}{\result}
\FPadd\result{\number\numexpr #2}{\result}
\result
}
\makeatother
\begin{document}
\huge
\bfseries Clamp Tests
\normalfont
Clamp -5 between 0 and 100: \clamp{-5}{0}{100}
Clamp 45 between 0 and 100: \clamp{45}{0}{100}
Clamp 150 between 0 and 100: \clamp{150}{0}{100}
Clamp -0.5 between 0 and 1: \clamp{-0.5}{0}{1}
Clamp 0.5 between 0 and 1: \clamp{0.5}{0}{1}
Clamp 1.5 between 0 and 1: \clamp{1.5}{0}{1}
\bfseries Lerp Tests
\normalfont
Lerp 0 between 0 and 100: \lerp{0}{0}{100}
Lerp 0.5 between 0 and 100: \lerp{0.5}{0}{100}
Lerp 1 between 0 and 100: \lerp{1}{0}{100}
\bfseries Unlerp Tests
\normalfont
Unlerp 0 between 0 and 100: \unlerp{0}{0}{100}
Unlerp 45 between 0 and 100: \unlerp{45}{0}{100}
Unlerp 150 between 0 and 100: \unlerp{100}{0}{100}
Unlerp 0.5 between 0 and 2: \unlerp{0.5}{0}{2}
\bfseries Combination Tests
\normalfont
Store manual value in variable: \def\testa{0.500000000000000000}
Use manual variable in clamp: \clamp{\testa}{0}{1}
Store unlerp result in variable: \def\testb{\unlerp{50}{0}{100}}
Output unlerp result variable: \testb
%Variable -> clamp: \clamp{\testb}{0}{1}
% Fails with the following error messages:
% ! Missing number, treated as zero.
% ! Illegal unit of measure (pt inserted).
% ! Missing = inserted for \ifdim.
%Unlerp -> Clamp: \clamp{\unlerp{50}{0}{100}}{0}{1}
% Fails with the following error messages:
% ! Missing number, treated as zero.
% ! Illegal unit of measure (pt inserted).
% ! Missing = inserted for \ifdim.
\end{document}
单独来看,它们似乎可以工作,但我很难将它们组合起来。如果我尝试通过嵌套它们的参数来调用它们,我会得到一个错误。我可以使用存储一个命令的输出\def
,然后将其显示在页面上,但只要我尝试将其传递给下一个命令,我就会得到同样的错误。失败的调用可以在我的示例底部看到,已被注释掉。
我收到的错误是:
Missing number, treated as zero.
Illegal unit of measure (pt inserted).
Missing = inserted for \ifdim.
(另外还有一堆重复上述内容的错误消息)
我究竟做错了什么?
答案1
我建议使用fp
即将推出的 -project 中的 -commands LaTeX3
,以免与fp
您正在使用的包混淆。fp
-package 很旧而且很笨重。
下面使用了LaTeX3
-project 或中的语法expl3
,该语法适用于包和类编写者。因此,它可能看起来有点神秘,但它有一些非常好的优点。在下面的代码中,我已将宏与常规 latex 语法一起使用,以便于输入,因此您根本不需要了解任何有关新语法的知识。只需像普通的-macro 一样\fpeval
使用即可。\fpeval{equation}
LaTeX
有了它,你可以进行大量计算,输入比包更容易fp
。特别是看到新宏变得多么简短和易于阅读。有许多数学函数可用,我在底部添加了其中几个作为示例。
您可以在以下位置找到有关可用功能及其用法的更多信息第二十二部分 l3fp 包:浮点的接口3文档。
请注意,您始终可以通过命令行/终端输入 来查找文档texdoc interface3
,这适用于任何软件包。该文档也可在以下位置找到:http://ctan.org/pkg/interface3
错误
该错误是由于扩展引起的。约瑟夫·赖特这里的答案给出了很好的解释以及为什么原始代码不起作用。
定义宏xparse
似乎可以解决这个问题。
编辑:
我已经删除了\fp_compare
as fpeval
hasmax(1,2,3)
和min(1,2,3)
available 函数,它们分别输出最大值和最小值。
我也听取了埃格尔并使得宏可扩展。
输出
代码
\documentclass[twoside]{memoir}
\usepackage[
papersize={8.5in,11in},
vmargin=0.5in,
outer=1in,
inner=0.5in,
includehead,
includefoot,
]{geometry}
\usepackage{xparse}
\ExplSyntaxOn % enable LaTeX3-syntax
% If you don't want to use syntax from LaTeX3 in your code, we can make them
% available as regular LaTeX-syntax by the following commands:
\cs_set_eq:NN \fpeval \fp_eval:n % Make fpeval available. Create a Control Sequence(macro) named `\fpeval`, and Set it Equal to LaTeX3-macro `\fp_eval`.
\ExplSyntaxOff % disable LaTeX3-syntax
\DeclareExpandableDocumentCommand{\clamp}{ m m m }{% Make a expandable macro,
% with 3 Mandatory arguments
\fpeval{min(max(#1,#2),#3)}
}
\DeclareExpandableDocumentCommand{\unlerp}{ m m m }{% Make a expandable macro,
% with 3 Mandatory arguments
\fpeval{ ( #1 - #2 ) / ( #3 - #2 ) }%
}
\DeclareExpandableDocumentCommand{\lerp}{ m m m }{% Make a expandable macro,
%with 3 Mandatory arguments
\fpeval{ ( #3 - #2 ) * #1 + #2 }%
}
\begin{document}
\huge
\bfseries Clamp Tests
\normalfont
Clamp -5 between 0 and 100: \clamp{-5}{0}{100}
Clamp 45 between 0 and 100: \clamp{45}{0}{100}
Clamp 150 between 0 and 100: \clamp{150}{0}{100}
Clamp -0.5 between 0 and 1: \clamp{-0.5}{0}{1}
Clamp 0.5 between 0 and 1: \clamp{0.5}{0}{1}
Clamp 1.5 between 0 and 1: \clamp{1.5}{0}{1}
\bfseries Lerp Tests
\normalfont
Lerp 0 between 0 and 100: \lerp{0}{0}{100}
Lerp 0.5 between 0 and 100: \lerp{0.5}{0}{100}
Lerp 1 between 0 and 100: \lerp{1}{0}{100}
\bfseries Unlerp Tests
\normalfont
Unlerp 0 between 0 and 100: \unlerp{0}{0}{100}
Unlerp 45 between 0 and 100: \unlerp{45}{0}{100}
Unlerp 150 between 0 and 100: \unlerp{100}{0}{100}
Unlerp 0.5 between 0 and 2: \unlerp{0.5}{0}{2}
\bfseries Combination Tests
\normalfont
Store manual value in variable: \def\testa{0.5}
Use manual variable in clamp: \clamp{\testa}{0}{1}
Store unlerp result in variable: \def\testb{\unlerp{50}{0}{100}}
Output unlerp result variable: \testb\
Variable \(\rightarrow\) clamp: \clamp{\testb}{0}{1}
\textbf{Easy calculations, just as an example:}
\verb|\fpeval{pi * 4^2 }| :
\fpeval{pi * 4^2 }
\verb|\fpeval{asind(\testb)}| :
\fpeval{asind(\testb)}
\end{document}
答案2
TeX 是一种宏扩展语言,因此不存在“返回”值这一说。对于可扩展宏,可以安排在使用结果之前进行扩展。在某些情况下,例如使用\ifdim
,这将是命令本身的一部分(\ifdim
执行扩展)。
执行的计算fp
不是以可扩展的方式完成的(它们在内部使用赋值)。因此,要使用,fp
您需要以不同的方式设置计算,将计算放在与比较相同的位置。如答案中所述鲁纳尔小偷,你最好使用可扩展的计算设置,比如中的那个expl3
。由于另一个答案涵盖了这一点,我不会进一步讨论它,但我想指出的是,你的答案中有很多空白(见行末百分号(%)有什么用?)您还可以使比较可扩展:
\newcommand\clamp[3]{%
\ifdim #1pt<#2pt
#2%
\else
\ifdim #1pt>#3pt
#3%
\else
#1%
\fi
\fi
}