Wolfram mathematica 如何在Mathematica中定义新的数值常量?
在Mathematica中定义数值常数的最佳方法是什么 例如,假设我希望Wolfram mathematica 如何在Mathematica中定义新的数值常量?,wolfram-mathematica,Wolfram Mathematica,在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]; 然后我可以在符号计算中使用它作为符号,当需要数值结果时,它将
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.0g
的计算结果为9.81
这似乎不像内置的数值常量那样与Mathematica紧密相连。例如,Pi>0
将计算为True
,但g>0
不会。(我可以将g>0
添加到全局$assessments
中,但即使这样,我也需要调用Simplify
才能使其生效。)
另外,Positive[g]
返回True
,但Positive[g^2]
不计算-使用Pi将其与等效语句进行比较
所以我的问题是,我还应该做什么来定义一个数值常数?可以设置哪些其他属性/属性?有没有更简单的方法?你可能想考虑使用单位而不是常数。Mathematica中有几个选项可用
与单位合作有很多技术问题和微妙之处。我发现设计师的单位非常有用。关于MathGroup也有一些有趣的讨论。也许我很天真,但在我看来,你的定义是一个好的开始。可以通过UpValues
添加g>0->True
之类的内容。要使正数[g^2]
返回真值
,您可能必须重载正数
,因为上限值的深度为1。通常,我认为涉及常数的自动计算表达式的精确集合是一个移动的目标,即使对于内置常数也是如此。换句话说,这些额外的内置规则似乎是根据方便性和频繁使用来确定的,是根据具体情况来确定的,而不是根据首要原则。只要你觉得需要,我就会在你前进的过程中添加新的规则。您可能无法期望您的常量像内置的一样集成到系统中,但我认为您可以非常接近。您可能需要在这些符号上重载许多内置函数,但是,这些函数是什么,将取决于您需要从符号中获得什么
编辑
我对是否包含这一点犹豫不决,因为下面的代码是一种黑客行为,但在某些情况下可能有用。代码如下:
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[391]:={f[g],g^2,g^2>0,2g,正[2g+1],正[2g-a],g^2+a^2,g^2+a^2>0,g0,g0,
g0,g我建议使用零参数“function”。这样,它既可以被赋予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当然,单位软件包很方便。自动单位软件包也有一个很好的相关功能。但是,也有一些物理常数,例如(和QFT中的其他基本无量纲常数)这是无量纲的。还有没有有效计算方案的数学常数,例如。因此单位包并不总是需要的。此外,您可能认为1米>0
应该返回True
…我希望“1米>0米”返回真值。但对我来说,将度量值与数字(例如“1米>0”)进行比较比比较不同维度的度量值(例如“1米>1秒”)更没有意义。对于具有确定零的单位(例如米,秒或开尔文),那么与零的比较是有意义的。对于单位是(比如经典物理学中的能量或摄氏度的温度),那么与零的比较就有点无意义了。旁白:0米将立即计算为0…1米~=3.34E-9秒<1秒你几乎肯定不幼稚,可能对你的其余答案是正确的。但我想我希望得到更多…@Simon你可以尝试添加这样一条规则:g/:f_[left_,g,right_]/;!MemberQ[{Clear,Remove,N},f]:=f[左,N[g],右]
在最后。对于g
上不求值的任何函数,它将用其数值替换g
。然而,这可能并不总是需要的,因为in将防止g
周围的惰性包装器和具有Hold属性的函数应用于g
,有时我们也不需要t结果是基于数值的。无论如何,像正[g^3]
或g>0
会起作用。但这肯定是一种黑客手段,而不是推荐的方法。莱昂尼德:我认为黑客手段去除了太多的肉。它会使,例如,2g
的数值达到19.62
。但我理解你的意思。@Simon我添加了一个更“精细的”编辑中我的黑客版本(不确定这样做是否正确,但太大,无法发表评论)。它仍然是一个黑客(可能更糟),但它确实解决了您对我上一个的一些批评。很酷的黑客,但丹尼尔的解决方案似乎完全符合我的要求,所以我想我必须给他打勾。除了必须随身携带[]
,这似乎具有我所寻找的所有属性。前者可以通过一些定制的n进行修复
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