首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在Mathematica中定义一个新的数值常量?

如何在Mathematica中定义一个新的数值常量?
EN

Stack Overflow用户
提问于 2011-11-26 10:28:03
回答 3查看 3.3K关注 0票数 11

在Mathematica中定义数值常量的最佳方法是什么?

例如,我希望g是地球表面由于重力而产生的近似加速度。我给它一个数值(在m/s^2中),用以下命令告诉Mathematica它是数值、正数和常量

代码语言:javascript
运行
复制
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的等效语句进行比较。

所以我的问题是,我还应该做什么来定义一个数值常量?还可以设置哪些其他属性/属性?有没有更简单的方法来解决这个问题?等等。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-11-27 06:22:30

我推荐使用零参数“函数”。这样,它就可以同时被赋予NumericFunction属性和一个数值求值规则。后者对于像肯定这样的谓词很重要。

代码语言:javascript
运行
复制
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

票数 5
EN

Stack Overflow用户

发布于 2011-11-26 10:53:55

也许我很天真,但在我看来,你的定义是一个很好的开始。像g > 0->True这样的东西可以通过UpValues添加。对于返回TruePositive[g^2],您可能必须重载Positive,因为UpValues的深度限制为1。一般来说,我认为涉及常量的精确的自动求值表达式集是一个移动的目标,即使对于内置常量也是如此。换句话说,这些额外的内置规则似乎是从便利性和频繁使用的角度出发,逐一确定的,而不是从最初的原则决定的。只要你觉得需要,我就会在你需要的时候添加新规则。你可能不能期望你的常量像内置的那样很好地集成在系统中,但我认为你可以非常接近。您可能必须在这些符号上重载许多内置函数,但同样,哪些将是那些将取决于您需要从符号中获得什么。

编辑

我还在犹豫要不要把它包括进来,因为下面的代码是一个hack,但它在某些情况下可能是有用的。代码如下:

代码语言:javascript
运行
复制
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]

这样,你就可以让一个符号在某些地方自动替换它的数值,在这些地方,我们指出围绕那些函数调用的一些函数可能会从中受益。下面是一个示例:

代码语言:javascript
运行
复制
ClearAll[g, f];
SetAttributes[g, Constant];
N[g] = 9.81;
NumericQ[g] ^= True;
defineAutoNValue[g];
f[g] := "Do something with g";

这里我们将尝试计算一些涉及g的表达式,首先通常是:

代码语言:javascript
运行
复制
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}

现在在我们的包装器中(第二个参数给出了一个规则列表,以指示哪些符号在包含这些符号的代码周围时,应该导致这些符号被替换为它们的数值):

代码语言:javascript
运行
复制
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}

由于以上是一个黑客攻击,我不能保证它的任何东西。它在某些情况下可能是有用的,但这必须根据具体情况来决定。

票数 3
EN

Stack Overflow用户

发布于 2011-11-26 10:49:18

您可能希望考虑使用单位,而不仅仅是常量。在Mathematica中有几个可用选项

  • Units
  • Automatic Units
  • Designer units

使用单元有相当多的技术问题和微妙之处。我发现Designer Units的backgrounder非常有用。在MathGroup上也有一些有趣的讨论。(例如here)。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8275850

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档