如何用数字方式展开 \fpeval{} 结果?

如何用数字方式展开 \fpeval{} 结果?

我正在尝试使用它xfp来创建一些自动化的家庭作业解决方案。对于短文档,它非常有效,但对于较长的文档,编译时间会成倍增加。例如:

\def\GDUbeta{30} % upstream beta
\def\GDUMa{3.0} % upstream Mach number
\def\GDUP{101} % upstream pressure
\def\GDUT{295} % upstream temp
%------ Modify initial values above this line ------ 
\def\GDUtheta{\fpeval{atand(2*cotd(\GDUbeta)*(\GDUMa^2*sind(\GDUbeta)^2-1)/( (1.4+cosd(2*\GDUbeta))*\GDUMa^2+2 ))}} % upstream theta
\def\GDUMan{\fpeval{\GDUMa*sind(\GDUbeta)}} % upstream Ma normal
\def\GDUPratio{\fpeval{1+2*1.4/(1.4+1)*(\GDUMan^2-1)}} % upstream pressure ratio
\def\GDUTratio{\fpeval{(1+2*1.4/(1.4+1)*(\GDUMan^2-1))*((2+(1.4-1)*\GDUMan^2)/((1.4+1)*\GDUMan^2))}} % upstream pressure ratio
\def\GDDMan{\fpeval{sqrt((2+(1.4-1)*\GDUMan^2)/(2*1.4*\GDUMan^2-(1.4-1)))}}
 % downstream Ma normal
\def\GDDMa{\fpeval{\GDDMan/sind(\GDUbeta-\GDUtheta)}} % downstream Ma
% Closed form solution of beta --->
\def\GDtanmu{\fpeval{tan(asin(1/\GDDMa))}} % tan Mach angle
\def\GDClosec{\fpeval{\GDtanmu^2}} 
\def\GDClosea{\fpeval{((1.4-1)/2+(1.4+1)/2*\GDClosec)*tand(\GDUtheta)}}
\def\GDCloseb{\fpeval{((1.4+1)/2+(1.4+3)/2*\GDClosec)*tand(\GDUtheta)}}
\def\GDClosed{\fpeval{sqrt(4*(1-3*\GDClosea*\GDCloseb)^3/((27*\GDClosea^2*\GDClosec+9*\GDClosea*\GDCloseb-2)^2)-1)}}
\def\GDClosee{\fpeval{(\GDCloseb+9*\GDClosea*\GDClosec)/(2*(1-3*\GDClosea*\GDCloseb))}}
\def\GDClosef{\fpeval{\GDClosed*(27*\GDClosea^2*\GDClosec+9*\GDClosea*\GDCloseb-2)/(6*\GDClosea*(1-3*\GDClosea*\GDCloseb))}}
\def\GDCloseg{\fpeval{tan(1/3*atan(1/\GDClosed))}}
\def\GDDbeta{\fpeval{atand(\GDClosee-\GDClosef*\GDCloseg)}}
% <--- Closed form solution of beta
\def\GDphi{\fpeval{\GDDbeta-\GDUtheta}} % angle of reflected shock
\def\GDRMa{\fpeval{\GDDMa*sind(\GDDbeta)}} % reflect shock Mach number
\def\GDRPratio{\fpeval{1+2*1.4/(1.4+1)*(\GDRMa^2-1)}} % reflect pressure ratio
\def\GDRTratio{\fpeval{\GDRPratio*((2+(1.4-1)*\GDRMa^2)/((1.4+1)*\GDRMa^2))}} % reflect temp ratio
\def\GDRMan{\fpeval{sqrt((2+(1.4-1)*\GDRMa^2)/(2*1.4*\GDRMa^2-(1.4-1)))}} % reflect pressure ratio
\def\GDRAMa{\fpeval{\GDRMan/sind(\GDphi)}} % reflected actual Mach number
\def\GDRP{\fpeval{\GDRPratio*\GDUPratio*\GDUP}} % reflected pressure
\def\GDRT{\fpeval{\GDRTratio*\GDUTratio*\GDUT}} % reflected temp
\def\GDSPratio{\fpeval{(1+(1.4-1)/2*\GDRAMa^2)^(1.4/(1.4-1))}} % stagnation pressure ratio
\def\GDSP{\fpeval{\GDSPratio*\GDRP/1000}} % stagnation pressure
\def\GDSTratio{\fpeval{1+(1.4-1)/2*\GDUMa^2}} % stagnation temp ratio
\def\GDST{\fpeval{\GDSTratio*\GDUT}} % stagnation temp
%------ DO NOT modify calculations above this line ------ 

上述计算 100% 有效,问题是每次我在家庭作业解决方案中插入这些中间值时,它都会递归调用其上方的所有宏,从而导致编译速度非常非常慢。

我知道这在 LaTeX 中是一种丑陋的编码,但是有没有什么方法可以扩展并缓存fpeval为浮点数,只是为了避免以指数增长的次数调用这些宏?

答案1

如果计算是静态的,即当您更改值时您会重新编译,并且每个值都严格依赖于以前计算的值,那么您可以尝试使用 进行\def更改\edef

如果没有,您可以尝试使用pgfmath declare function,但准确性会受到影响(有时会受到很大影响)。

答案2

问题是,当你使用,比如说\GDUtheta\GDDMa您不是在应用值,而是在应用计算值所需的操作。

如果你已经仔细地布置了变量,使得每个变量只依赖于前面的变量,那么你可以評估。

我建议使用内置方法。

\documentclass{article}

\ExplSyntaxOn

\NewDocumentCommand{\fpset}{mm}
 {
  \fp_zero_new:N #1
  \fp_set:Nn #1 { #2 }
 }
\NewExpandableDocumentCommand{\fpuse}{m}{\fp_use:N #1}

\ExplSyntaxOff

\fpset\GDUbeta{30} % upstream beta
\fpset\GDUMa{3.0} % upstream Mach number
\fpset\GDUP{101} % upstream pressure
\fpset\GDUT{295} % upstream temp
%------ Modify initial values above this line ------ 
\fpset\GDUtheta{atand(2*cotd(\GDUbeta)*(\GDUMa^2*sind(\GDUbeta)^2-1)/( (1.4+cosd(2*\GDUbeta))*\GDUMa^2+2 ))} % upstream theta
\fpset\GDUMan{\GDUMa*sind(\GDUbeta)} % upstream Ma normal
\fpset\GDUPratio{1+2*1.4/(1.4+1)*(\GDUMan^2-1)} % upstream pressure ratio
\fpset\GDUTratio{(1+2*1.4/(1.4+1)*(\GDUMan^2-1))*((2+(1.4-1)*\GDUMan^2)/((1.4+1)*\GDUMan^2))} % upstream pressure ratio
\fpset\GDDMan{sqrt((2+(1.4-1)*\GDUMan^2)/(2*1.4*\GDUMan^2-(1.4-1)))}
 % downstream Ma normal
\fpset\GDDMa{\GDDMan/sind(\GDUbeta-\GDUtheta)} % downstream Ma
% Closed form solution of beta --->
\fpset\GDtanmu{tan(asin(1/\GDDMa))} % tan Mach angle
\fpset\GDClosec{\GDtanmu^2} 
\fpset\GDClosea{((1.4-1)/2+(1.4+1)/2*\GDClosec)*tand(\GDUtheta)}
\fpset\GDCloseb{((1.4+1)/2+(1.4+3)/2*\GDClosec)*tand(\GDUtheta)}
\fpset\GDClosed{sqrt(4*(1-3*\GDClosea*\GDCloseb)^3/((27*\GDClosea^2*\GDClosec+9*\GDClosea*\GDCloseb-2)^2)-1)}
\fpset\GDClosee{(\GDCloseb+9*\GDClosea*\GDClosec)/(2*(1-3*\GDClosea*\GDCloseb))}
\fpset\GDClosef{\GDClosed*(27*\GDClosea^2*\GDClosec+9*\GDClosea*\GDCloseb-2)/(6*\GDClosea*(1-3*\GDClosea*\GDCloseb))}
\fpset\GDCloseg{tan(1/3*atan(1/\GDClosed))}
\fpset\GDDbeta{atand(\GDClosee-\GDClosef*\GDCloseg)}
% <--- Closed form solution of beta
\fpset\GDphi{\GDDbeta-\GDUtheta} % angle of reflected shock
\fpset\GDRMa{\GDDMa*sind(\GDDbeta)} % reflect shock Mach number
\fpset\GDRPratio{1+2*1.4/(1.4+1)*(\GDRMa^2-1)} % reflect pressure ratio
\fpset\GDRTratio{\GDRPratio*((2+(1.4-1)*\GDRMa^2)/((1.4+1)*\GDRMa^2))} % reflect temp ratio
\fpset\GDRMan{sqrt((2+(1.4-1)*\GDRMa^2)/(2*1.4*\GDRMa^2-(1.4-1)))} % reflect pressure ratio
\fpset\GDRAMa{\GDRMan/sind(\GDphi)} % reflected actual Mach number
\fpset\GDRP{\GDRPratio*\GDUPratio*\GDUP} % reflected pressure
\fpset\GDRT{\GDRTratio*\GDUTratio*\GDUT} % reflected temp
\fpset\GDSPratio{(1+(1.4-1)/2*\GDRAMa^2)^(1.4/(1.4-1))} % stagnation pressure ratio
\fpset\GDSP{\GDSPratio*\GDRP/1000} % stagnation pressure
\fpset\GDSTratio{1+(1.4-1)/2*\GDUMa^2} % stagnation temp ratio
\fpset\GDST{\GDSTratio*\GDUT} % stagnation temp
%------ DO NOT modify calculations above this line ------ 

\begin{document}

GDRPratio = \fpuse{\GDRPratio}

GDST = \fpuse{\GDST}

GDUT = \fpuse{\GDUT}

\end{document}

在此处输入图片描述

相关内容