【问题标题】:Function types declarations in MathematicaMathematica 中的函数类型声明
【发布时间】:2011-08-02 03:05:30
【问题描述】:

我已经多次遇到过这个问题,关于mathematica 对函数理解的输入数据声明的类型。

似乎 Mathematica 理解以下类型声明: _整数, _列表, _?MatrixQ, _?VectorQ

但是:例如,_Real,_Complex 声明会导致函数有时无法计算。知道为什么吗?

这里的一般规则是什么?

【问题讨论】:

  • 所问的内容不干净。请给出示例代码和/或进一步的解释。
  • @Mr. Wizard:我稍微编辑了一下,但我认为问题已经很清楚了,下面提供的答案有助于解决我遇到的问题。例如,我不明白为什么在输入具有 Real 类型限制的整数时,它会返回 false。无论如何,下面的答案真的可以帮助我深入了解这个问题并有用地扩展......

标签: function types wolfram-mathematica


【解决方案1】:

当您执行f[x_]:=Sin[x] 之类的操作时,您所做的是定义模式替换规则。如果您改为使用f[x_smth]:=5(如果您同时尝试,请在第二个示例之前使用Clear[f]),您实际上是在说“无论您在哪里看到f[x],请检查x 的头部是否为smth,如果是,替换为 5"。例如,尝试

Clear[f]
f[x_smth]:=5
f[5]
f[smth[5]]

所以,为了回答你的问题,规则是在f[x_hd]:=1; 中,hd 可以是任何东西,并且与 x 的头部匹配。

也可以有更复杂的定义,比如f[x_] := Sin[x] /; x > 12,如果x>12就会匹配(当然可以任意复杂化)。

编辑:我忘记了真实部分。您当然可以定义Clear[f];f[x_Real]=Sin[x],它适用于例如 f[12.]。但是你要记住,Head[12.]RealHead[12]Integer,这样你的定义就不会匹配。

【讨论】:

    【解决方案2】:

    最可能的问题是您用于测试功能的输入。例如,

    f[x_Complex]:= Conjugate[x]
    f[x + I y]
    f[3 + I 4]
    

    返回

    f[x + I y]
    3 - I 4
    

    查看FullForms 时会发现第二个有效而第一个无效的原因

    x + I y // FullForm == Plus[x, Times[ Complex[0,1], y]]
    3 + I 4 // FullForm == Complex[3,4]
    

    在内部,Mathematica 将3 + I 4 转换为Complex 对象,因为每个项都是数字,但x + I y 没有得到与xy 相同的处理Symbols。同样,如果我们定义

    g[x_Real] := -x
    

    并使用它们

    g[ 5 ]  == g[ 5 ]
    g[ 5. ] == -5.
    

    这里的关键是5 是一个Integer,它不被识别为Real 的子集,但是通过添加小数点它变成Real

    正如acl 指出的那样,模式_Something 表示匹配任何带有Head === Something 的东西,_Real_Complex 的情况在给定Heads 的情况下都非常严格。

    【讨论】:

    • Integer 在数学上完全有效时,为什么不能将 Integer 识别为 Real 的子集?
    • @RM,我认为这是因为模式匹配机制的工作原理,因为它只查看表达式的Head。因此,当您键入 55. 时,您会得到 Integer 表达式与 Real 表达式。然后模式匹配器只看到头部不匹配。如果您想同时匹配两者,请使用_?NumericQ。当内部更改表达式足以不再匹配时,当匹配模式时,您总是会遇到这个问题。对我来说,最臭名昭著的是收集复杂表达式的虚部......
    • @R. M. 头部匹配和一般的模式匹配没有数学有效性的概念——唯一关心的是表达式的结构形式。数学有效性的概念需要明确编程。例如,如果想要一个适用于数学意义上的任何实数的函数,可以写成f[x_ /; x \[Element] Reals] := ...
    • @rcollyer:只是为了笑,我尝试了一个微基准测试:Timing[Do[f[10], {10000000}]] 用于两种变体。 /; 的运行时间是 ? 所需时间的 75%。我不会过多解读这个结果。在 Mathematica 中,表现力和清晰度通常比性能更重要。我会继续写下上下文中最清晰的形式。工作中也有个人喜好——我碰巧用了'/;'很多。 YMMV。当性能很重要时,人们可能会寻找不同的算法,或者如果失败了,则使用 Compile 或符号 C 或其他东西。
    • @WReach 原因可能是ConditionFullFormPatternTestFullFormFunction 简单得多:f[x_ /; x \[Element] Reals] // FullFormf[x_?(Element[#, Reals] &)] // FullForm。没有Function PatternTest 会稍微快一些:ClearAll[f]; f[x_?NumericQ] := x; Timing[Do[f[10], {20000000}]]ClearAll[f]; f[x_ /; NumericQ[x]] := x; Timing[Do[f[10], {20000000}]]。这证实了您的见解,即我们应该编写上下文中最清晰的任何形式。
    【解决方案3】:

    只是一个简短的说明,因为没有其他人提到它。您可以对多个 Heads 进行模式匹配 - 这比使用 ?/; 的条件匹配要快。

    f[x:(_Integer|_Real)] := True (* function definition goes here *)
    

    对于作用于 Real 或 Integer 参数的简单函数,它在大约 75% 的时间内运行,类似于类似的定义

    g[x_] /; Element[x, Reals] := True (* function definition goes here *)
    

    (正如 WReach 指出的那样,它在 75% 的时间内运行
    g[x_?(Element[#, Reals]&)] := True)。

    后一种形式的优点是它适用于符号常量,例如Pi - 尽管如果您想要一个纯数字函数,可以使用N 在前一种形式中修复。

    【讨论】:

    • 像这样匹配多个磁头非常脆弱。很容易忘记一种类型的表达式,因为您在这里忘记了Rational,或者类似Sqrt[2](不仅仅是Pi)。如果您需要检查表达式是否仅为数字(而不是是否有虚部),x_?NumericQ 是最好的。
    • @Szabolcs:我本来想Rational,因为我检查它不包括复杂的有理数,然后我忘了包括它!是的...作用于RealsRationals 的各种数字函数会破坏头部检查。所以你是对的,NumericQ 结合一个可选的检查来查看它是否在 Reals 中可能是最好的/最健壮的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多