我遇到了一个我想解决但自己无法解决的问题。我的目的是创建一个具有不同参数的组件库,并使用 FPeval 进行计算。以下是代码:
\documentclass{article}
\usepackage{fp}% http://ctan.org/pkg/fp
\usepackage{xstring}% http://ctan.org/pkg/xstring
\usepackage{xparse}% http://ctan.org/pkg/xparse
\usepackage{color}
%STRUCT
\newcommand \Rmin[2]{\ensuremath{\FPeval{\result}{round(#1-(#1*#2/100),2)}\result}}
\newcommand \Rmax[2]{\ensuremath{\FPeval{\result}{round(#1+(#1*#2/100),2)}\result}}
\newcommand\defResCMtype[2]{%defined VARIOUS types
\expandafter\newcommand\csname TOL#1\endcsname{#2}
}
\newcommand\defResCM[3]{%
\expandafter\newcommand\csname value#1\endcsname{#2}
\expandafter\newcommand\csname #1min\endcsname{
\StrDel{#3}{ }[\tmp]% remove spaces and store the string in \tmp
\IfEqCase{\tmp}{{typeX}{\Rmin{#2}{\TOLtypeX}}
}%
[{\color{red}XXXXXX}] %ERROR
}
\expandafter\newcommand\csname #1max\endcsname{
\StrDel{#3}{ }[\tmp]% remove spaces and store the string in \tmp
\IfEqCase{\tmp}{{typeX}{\Rmax{#2}{\TOLtypeX}}
}%
[{\color{red}XXXXXX}] %ERROR
}
}
%LIB
\defResCMtype{typeX}{5}
\defResCM{compX}{100}{typeX}
%CALC
\newcommand \calc[2]{\ensuremath{\FPeval{\result}{round(#1,#2)}\result}}
\newcommand \testcalcA{\ensuremath{\calc{(105 / 95)}{2}}} %calculated with numbers
\newcommand \testcalcB{\ensuremath{\calc{((\compXmax)/(\compXmin))}{2}}} %calculated with macros -> NOT WORKING
\begin{document}
test = \valuecompX \\
test2= \compXmax \\
test3= \compXmin \\
A = \testcalcA \\ %-> WORKING
%B = \testcalcB \\ %-> NOT WORKING
\end{document}
test2
如果我手动输入由&创建的数字,test3
则 FPeval 会计算方程式A
,但是,如果我想自动将这些值作为(\compXmax)
&(\compXmin)
或甚至comXmax
&comXmin
传递
\newcommand \testcalcB{\ensuremath{\calc{((\compXmax)/(\compXmin))}{2}}}
我收到一个错误! Use of \@newline doesn't match its definition.\kernel@ifnextchar ...rved@d =#1\def \reserved@a {#2}\def \reserved@b {#3}\f... B = \testcalcB
。
在文档中的计算之间手动插入数字很容易出错,我非常希望避免这种情况,因为直接在库中更新参数需要更新使用这些参数的整个文档。
答案1
关键是你想要\compXmin
并\compXmax
在其分配时进行评估,而无需在其定义中嵌入实际的计算。
已编辑,允许通过使用来在序言中设置库(在 OP 的评论中提到)\AtBeginDocument{}
。已重新编辑以保存中间计算(\testcalcB
结果保存在 中\thetestcalcB
,\testcalcC
结果保存在 中\thetestcalcC
)。
\documentclass{article}
\usepackage{fp}% http://ctan.org/pkg/fp
\usepackage{xstring}% http://ctan.org/pkg/xstring
\usepackage{xparse}% http://ctan.org/pkg/xparse
\usepackage{xcolor}
%STRUCT
\newcommand \Rmin[2]{\ensuremath{\FPeval{\result}{round(#1-(#1*#2/100),2)}%
\xdef\theRmin{\result}}}
\newcommand \Rmax[2]{\ensuremath{\FPeval{\result}{round(#1+(#1*#2/100),2)}%
\xdef\theRmax{\result}}}
\newcommand\defResCMtype[2]{%defined VARIOUS types
\expandafter\def\csname TOL#1\endcsname{#2}%
\ignorespaces}
\newcommand\defResCM[3]{%
\expandafter\def\csname value#1\endcsname{#2}%
\StrDel{#3}{ }[\tmp]% remove spaces and store the string in \tmp
\IfEqCase{\tmp}{{typeX}{\Rmin{#2}{\TOLtypeX}\Rmax{#2}{\TOLtypeX}%
\expandafter\xdef\csname #1max\endcsname{\theRmax}%
\expandafter\xdef\csname #1min\endcsname{\theRmin}%
}%
}%
[{\unskip\textcolor{red}{ERROR DEFINING: #1}\par}] %ERROR
\ignorespaces}
%LIB
\AtBeginDocument{
\defResCMtype{typeX}{5}
\defResCM{compX}{100}{typeX}
\defResCMtype{typeX}{10}
\defResCM{altX}{150}{typeX}
\defResCM{compY}{200}{type Y}
}
%CALC
\newcommand \calc[2]{\ensuremath{\FPeval{\result}{round(#1,#2)}}%
\xdef\thecalc{\result}}
\newcommand \testcalcB[1]{\ensuremath{\calc{((\csname#1max\endcsname)/%
(\csname#1min\endcsname))}{2}}%
\edef\thetestcalcB{\thecalc}\thetestcalcB}
\newcommand \testcalcC[1] {\ensuremath{\calc{(\thetestcalcB * \csname#1min\endcsname)}%
{2}}\edef\thetestcalcC{\thecalc}\thetestcalcC}
\begin{document}
test = \valuecompX \par
test2= \compXmax \par
test3= \compXmin \par
\medskip
B = \testcalcB{compX} \par %-> NOW WORKING
C = \testcalcC{compX} \par %-> NOW WORKING
\medskip
test = \valuealtX \par
test2= \altXmax \par
test3= \altXmin \par
\medskip
B = \testcalcB{altX} \par %-> NOW WORKING
C = \testcalcC{altX} \par %-> NOW WORKING
\end{document}