有时我想要/必须将计算分解为一系列步骤,因为我有一个想要在未来的计算中使用的术语,但由于有效数字很重要,所以我需要调整数字。
虽然不是最现实的,但我的 MWE 表明我使用expl3
函数\fp_eval:n
评估数学表达式的努力不能将siunitx
舍入结果用作未来的输入。
示例:我们不使用完整的二次公式,而是将其分解为两个累积项来显示有效数字精度损失的影响:即,我们不在内存中一次评估整个表达式,而是将其分解为X1 = T1 + T2
或,X2 = T1 - T2
其中T1
和T2
已经被评估并简化为说明性有效数字。
T1
使用我的函数来求解和没有任何问题T2
,但是使用T1
和T2
来计算X1
和X2
却会失败。
组合的fp_eval
、\num
和分别用于求值、舍入和存储(用于继续使用)在下面的 MWE 中,但是,如果不生成我认为是错误的内容,newcommand
我就无法成功调用第二轮命令。MyEval
not a number
\documentclass[letter,12pt]{article}
\usepackage{expl3}
\usepackage{parskip}
\usepackage{setspace}
\usepackage{siunitx}
\usepackage{mathtools,amssymb}
%\ExplSyntaxOn
% \cs_set_eq:NN \fpeval \fp_eval:n
%\ExplSyntaxOff
\ExplSyntaxOn
\NewDocumentCommand {\MyEval} {m O{6} m}
{
\newcommand{#1}{
\num[round-mode=figures,round-precision=#2]{\fp_eval:n {#3}}
}
}
\ExplSyntaxOff
\newcommand{\MySF}{6}
%\newcommand{\MyEval}[2]{%
% \newcommand{#1}{%
% \num[round-mode=figures,round-precision=4]{%
% \fpeval{#2}%
% }%
% }%
%}%
\begin{document}\noindent
\textbf{Quadratic Equation}: $x^2 + 40x + 2 = 0$
\renewcommand{\MySF}{4}
\newcommand{\qa}{1}
\newcommand{\qb}{40}
\newcommand{\qc}{2}
%\MyEval{\QuadraticxOne}[\MySF]{(1/2)*(1/\qa)*(-\qb + ((\qb)^2-(4*\qa*\qc))^(1/2))}
%\MyEval{\QuadraticxTwo}[\MySF]{(1/2)*(1/\qa)*(-\qb - ((\qb)^2-(4*\qa*\qc))^(1/2))}
\MyEval{\QuadratictOne}[\MySF]{(1/2)*(1/\qa)*(-\qb)}
\MyEval{\QuadratictTwo}[\MySF]{(1/2)*(1/\qa)*(((\qb)^2-(4*\qa*\qc))^(1/2))}
\MyEval{\QuadraticxOne}[\MySF]{\QuadratictOne+\QuadratictTwo}
\MyEval{\QuadraticxTwo}[\MySF]{\QuadratictOne-\QuadratictTwo}
\begin{equation*}\begin{aligned}
t_1 = \QuadratictOne\\
t_2 = \QuadratictTwo\\
%x_1 = \QuadraticxOne\\
%x_2 = \QuadraticxTwo\\
\end{aligned} \end{equation*}
\end{document}
答案1
\num
是命令印刷数字,而不是操纵它们。浮点运算包括round
。
\documentclass{article}
\usepackage{xparse}
\usepackage{siunitx}
\usepackage{mathtools,amssymb}
\ExplSyntaxOn
\NewDocumentCommand {\MyEval} {m O{6} m}
{
\tl_new:N #1
\tl_set:Nx #1 { \fp_eval:n { round( (#3) , #2 ) } }
}
\ExplSyntaxOff
\newcommand{\MySF}{6}
\begin{document}
\textbf{Quadratic Equation}: $x^2 + 40x + 2 = 0$
\renewcommand{\MySF}{4}
\newcommand{\qa}{1}
\newcommand{\qb}{40}
\newcommand{\qc}{2}
\MyEval{\QuadratictOne}[\MySF]{(1/2)*(1/\qa)*(-\qb)}
\MyEval{\QuadratictTwo}[\MySF]{(1/2)*(1/\qa)*(((\qb)^2-(4*\qa*\qc))^(1/2))}
\MyEval{\QuadraticxOne}[\MySF]{\QuadratictOne+\QuadratictTwo}
\MyEval{\QuadraticxTwo}[\MySF]{\QuadratictOne-\QuadratictTwo}
\begin{align*}
t_1 &= \QuadratictOne\\
t_2 &= \QuadratictTwo\\
x_1 &= \QuadraticxOne\\
x_2 &= \QuadraticxTwo
\end{align*}
\end{document}
请注意,我\tl_set:Nx
这样说是进行全面评估。
评论后有新版本
您需要将计算步骤与打印步骤分开。
\documentclass{article}
\usepackage{xparse}
\usepackage{siunitx}
\usepackage{mathtools,amssymb}
\ExplSyntaxOn
\NewDocumentCommand {\MyEval} {mm}
{
\tl_new:N #1
\tl_set:Nx #1 { \fp_eval:n { #2 } }
}
\NewDocumentCommand{\MyNum}{O{6}m}
{
\num[round-mode=figures,round-precision=#1]{#2}
}
\ExplSyntaxOff
\newcommand{\MySF}{6}
\begin{document}
\textbf{Quadratic Equation}: $x^2 + 40x + 2 = 0$
\renewcommand{\MySF}{4}
\newcommand{\qa}{1}
\newcommand{\qb}{40}
\newcommand{\qc}{2}
\MyEval{\QuadratictOne}{(1/2)*(1/\qa)*(-\qb)}
\MyEval{\QuadratictTwo}{(1/2)*(1/\qa)*(((\qb)^2-(4*\qa*\qc))^(1/2))}
\MyEval{\QuadraticxOne}{\QuadratictOne+\QuadratictTwo}
\MyEval{\QuadraticxTwo}{\QuadratictOne-\QuadratictTwo}
\begin{align*}
t_1 &= \MyNum{\QuadratictOne}\\
t_2 &= \MyNum{\QuadratictTwo}\\
x_1 &= \MyNum[\MySF]{\QuadraticxOne}\\
x_2 &= \MyNum[\MySF]{\QuadraticxTwo}
\end{align*}
\end{document}
答案2
因此,siunitx
我可以使用以下方法将值以数字方式处理为 SDF 有效数字:
ROUND(值,SDF-(1+INT(LOG10(ABS(值)))))
此外,能够重用和更新计算很有用,因此为了使同一变量的计算能够逐步更新,我添加了一个检查(\cs_if_exist:NF #1 {\tl_new:N #1}
)来确定命令是否已经存在,以防止出现提示文档命令已存在的错误。
因此 MWE 变成
\documentclass{article}
\usepackage{xparse}
\usepackage{siunitx}
\usepackage{mathtools,amssymb}
\ExplSyntaxOn
\NewDocumentCommand {\MySFRound} {m O{6} m}
{
\cs_if_exist:NF #1 {\tl_new:N #1}
\tl_set:Nx #1 { \fp_eval:n { round( (#3) , (#2 - (1 + floor(ln(abs(#3))/ln(10)))) ) } }
%ROUND(value,SDF-(1+INT(LOG10(ABS(value)))))
}
\ExplSyntaxOff
\newcommand{\MySF}{6}
\begin{document}
\textbf{Quadratic Equation}: $x^2 + 40x + 2 = 0$
\renewcommand{\MySF}{4}
\newcommand{\qa}{1}
\newcommand{\qb}{40}
\newcommand{\qc}{2}
\MySFRound{\QuadratictOne}[\MySF]{(1/2)*(1/\qa)*(-\qb)}
\MySFRound{\QuadratictTwo}[\MySF]{(1/2)*(1/\qa)*(((\qb)^2-(4*\qa*\qc))^(1/2))}
\MySFRound{\QuadraticxOne}[\MySF]{\QuadratictOne+\QuadratictTwo}
\MySFRound{\QuadraticxTwo}[\MySF]{\QuadratictOne-\QuadratictTwo}
\begin{align*}
t_1 &= \QuadratictOne\\
t_2 &= \QuadratictTwo\\
x_1 &= \QuadraticxOne\\
x_2 &= \QuadraticxTwo
\end{align*}
\end{document}
注意:在实现任意底数的对数之前,您可以使用ln(X)/ln(10)
来求解log_10(X)
(expl3 数学函数中的对数)