Wolfram 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]; 然后我可以在符号计算中使用它作为符号,当需要数值结果时,它将

在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.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