在Mathematica中定义数值常量的最佳方法是什么?
例如,我希望g
是地球表面由于重力而产生的近似加速度。我给它一个数值(在m/s^2
中),用以下命令告诉Mathematica它是数值、正数和常量
Unprotect[g];
ClearAll[g]
N[g] = 9.81;
NumericQ[g] ^= True;
Positive[g] ^= True;
SetAttributes[g, Constant];
Protect[g];
然后,我可以将它用作符号计算中的符号,当调用数值结果时,符号计算将自动计算为9.81。例如,1.0 g
的计算结果为9.81
。
这似乎不像内置的数值常量那样与Mathematica捆绑在一起。例如,Pi > 0
将计算为True
,但g > 0
不会。(我可以将g > 0
添加到全局$Assumptions
中,但即使这样,也需要调用Simplify
才能生效。)此外,Positive[g]
返回True
,但Positive[g^2]
不求值-将其与使用Pi
的等效语句进行比较。
所以我的问题是,我还应该做什么来定义一个数值常量?还可以设置哪些其他属性/属性?有没有更简单的方法来解决这个问题?等等。
发布于 2011-11-27 06:22:30
我推荐使用零参数“函数”。这样,它就可以同时被赋予NumericFunction属性和一个数值求值规则。后者对于像肯定这样的谓词很重要。
SetAttributes[gravUnit, NumericFunction]
N[gravUnit[], prec_: $MachinePrecision] := N[981/100, prec]
In[121]:= NumericQ[gravitUnit[]]
Out[121]= True
In[122]:= Positive[gravUnit[]^2 - 30]
Out[122]= True
Daniel Lichtblau
发布于 2011-11-26 10:53:55
也许我很天真,但在我看来,你的定义是一个很好的开始。像g > 0->True
这样的东西可以通过UpValues
添加。对于返回True
的Positive[g^2]
,您可能必须重载Positive
,因为UpValues
的深度限制为1。一般来说,我认为涉及常量的精确的自动求值表达式集是一个移动的目标,即使对于内置常量也是如此。换句话说,这些额外的内置规则似乎是从便利性和频繁使用的角度出发,逐一确定的,而不是从最初的原则决定的。只要你觉得需要,我就会在你需要的时候添加新规则。你可能不能期望你的常量像内置的那样很好地集成在系统中,但我认为你可以非常接近。您可能必须在这些符号上重载许多内置函数,但同样,哪些将是那些将取决于您需要从符号中获得什么。
编辑
我还在犹豫要不要把它包括进来,因为下面的代码是一个hack,但它在某些情况下可能是有用的。代码如下:
Clear[evalFunction];
evalFunction[fun_Symbol, HoldComplete[sym_Symbol]] := False;
Clear[defineAutoNValue];
defineAutoNValue[s_Symbol] :=
Module[{inSUpValue},
s /: expr : f_[left___, s, right___] :=
Block[{inSUpValue = True},
With[{stack = Stack[_]},
If[
expr === Unevaluated[expr] &&
(evalFunction[f, HoldComplete[s]] ||
MemberQ[
stack,
HoldForm[(op_Symbol /; evalFunction[op, HoldComplete[s]])
[___, x_ /; ! FreeQ[Unevaluated[x], HoldPattern@expr], ___]],
Infinity
]
),
f[left, N[s], right],
(* else *)
expr
]]] /; ! TrueQ[inSUpValue]];
ClearAll[substituteNumeric];
SetAttributes[substituteNumeric, HoldFirst];
substituteNumeric[code_, rules : {(_Symbol :> {__Symbol}) ..}] :=
Internal`InheritedBlock[{evalFunction},
MapThread[
Map[Function[f, evalFunction[f, HoldComplete[#]] = True], #2] &,
Transpose[List @@@ rules]
];
code]
这样,你就可以让一个符号在某些地方自动替换它的数值,在这些地方,我们指出围绕那些函数调用的一些函数可能会从中受益。下面是一个示例:
ClearAll[g, f];
SetAttributes[g, Constant];
N[g] = 9.81;
NumericQ[g] ^= True;
defineAutoNValue[g];
f[g] := "Do something with g";
这里我们将尝试计算一些涉及g
的表达式,首先通常是:
In[391]:= {f[g],g^2,g^2>0, 2 g, Positive[2 g+1],Positive[2g-a],g^2+a^2,g^2+a^2>0,g<0,g^2+a^2<0}
Out[391]= {Do something with g,g^2,g^2>0,2 g,Positive[1+2 g],
Positive[-a+2 g],a^2+g^2,a^2+g^2>0,g<0,a^2+g^2<0}
现在在我们的包装器中(第二个参数给出了一个规则列表,以指示哪些符号在包含这些符号的代码周围时,应该导致这些符号被替换为它们的数值):
In[392]:=
substituteNumeric[{f[g],g^2,g^2>0, 2 g, Positive[2 g+1],Positive[2g-a],g^2+a^2,g^2+a^2>0,
g<0,g^2+a^2<0},
{g:>{Positive,Negative,Greater}}]
Out[392]= {Do something with g,g^2,True,2 g,True,Positive[19.62\[VeryThinSpace]-a],
a^2+g^2,96.2361\[VeryThinSpace]+a^2>0,g<0,a^2+g^2<0}
由于以上是一个黑客攻击,我不能保证它的任何东西。它在某些情况下可能是有用的,但这必须根据具体情况来决定。
发布于 2011-11-26 10:49:18
您可能希望考虑使用单位,而不仅仅是常量。在Mathematica中有几个可用选项
使用单元有相当多的技术问题和微妙之处。我发现Designer Units的backgrounder非常有用。在MathGroup上也有一些有趣的讨论。(例如here)。
https://stackoverflow.com/questions/8275850
复制相似问题