Function Mathematica中的函数类型声明

Function Mathematica中的函数类型声明,function,types,wolfram-mathematica,Function,Types,Wolfram Mathematica,关于mathematica理解的函数输入数据声明类型,我已经多次碰到这个问题 Mathematica似乎理解以下类型的声明: _整数, _名单, _?MatrixQ, _?矢量 但是:_Real,_复杂的声明会导致函数有时无法计算。知道为什么吗 这里的一般规则是什么?当您执行类似于f[x]:=Sin[x]的操作时,您所做的是定义一个模式替换规则。如果您改为说f[x\u smth]:=5(如果您在第二个示例之前同时尝试这两种方法,请在前面清除[f]),您实际上是在说“无论在哪里看到f[x],请检查

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

Mathematica似乎理解以下类型的声明: _整数, _名单, _?MatrixQ, _?矢量

但是:_Real,_复杂的声明会导致函数有时无法计算。知道为什么吗


这里的一般规则是什么?

当您执行类似于
f[x]:=Sin[x]
的操作时,您所做的是定义一个模式替换规则。如果您改为说
f[x\u smth]:=5(如果您在第二个示例之前同时尝试这两种方法,请在前面清除[f]
),您实际上是在说“无论在哪里看到
f[x]
,请检查
x
的头部是否为
smth
,如果是,则替换为5”。比如说,

Clear[f]
f[x_smth]:=5
f[5]
f[smth[5]]
f[x_Complex]:= Conjugate[x]
f[x + I y]
f[3 + I 4]
所以,为了回答你的问题,规则是在
f[x_hd]:=1
hd
可以是任何东西,并且与x的头部匹配

你也可以有更复杂的定义,比如
f[x_]:=Sin[x]/;x>12
,如果x>12,则匹配(当然,这可能会变得任意复杂)


编辑:我忘记了真实的部分。您当然可以定义
Clear[f];f[x_Real]=Sin[x]
它适用于eg f[12]。但是您必须记住,
Head[12.]
Real
Head[12]
Integer
,因此您的定义将不匹配。

最可能的问题是用于测试函数的输入。比如说,

Clear[f]
f[x_smth]:=5
f[5]
f[smth[5]]
f[x_Complex]:= Conjugate[x]
f[x + I y]
f[3 + I 4]
返回

f[x + I y]
3 - I 4
查看他们的
FullForm
s时,会发现第二个有效而第一个无效的原因

x + I y // FullForm == Plus[x, Times[ Complex[0,1], y]]
3 + I 4 // FullForm == Complex[3,4]
在内部,Mathematica将
3+i4
转换为
复杂的
对象,因为每个术语都是数字,但是
x+iy
没有得到与
x
y
符号的相同处理。同样,如果我们定义

g[x_Real] := -x
并使用它们

g[ 5 ]  == g[ 5 ]
g[ 5. ] == -5.
这里的关键是
5
是一个
整数
,它不被识别为
Real
的子集,但通过添加小数点,它就变成了
Real


正如所指出的,模式
\u Something
意味着匹配任何具有
头部===Something
的事物,而
\u Real
\u Complex
案例在给定这些
头部的情况下都非常严格。

只是一个简短的注释,因为没有人提到过它。您可以对多个
头进行模式匹配,这比使用
/的条件匹配更快

f[x:(_Integer|_Real)] := True (* function definition goes here *)
对于作用于实数或整数参数的简单函数,其运行时间约为类似定义的75%

g[x_] /; Element[x, Reals] := True (* function definition goes here *)
(正如花环所指出的,它在75%的时间内运行
as
g[x#?(元素[#,实数]&)]:=True


后一种形式的优点是它适用于符号常量,如
Pi
——尽管如果你想要一个纯数值函数,这可以通过使用
N

在数学上完全有效时,mma为什么不将
整数
识别为
的子集?@RM,我认为这是因为模式匹配机制是如何工作的,因为它只查看表达式的
头部。因此,当您键入
5
5.
时,您将得到一个
整数
表达式与一个
实数
表达式。然后,模式匹配器只看到头部不匹配。如果要同时匹配这两个选项,请使用
\uuux-NumericQ
。在匹配模式时,当一个内部变量改变了表达式,使其不再匹配时,始终会遇到这个问题。对我来说,最臭名昭著的是收集复杂表达式的虚部…@R.M.头部匹配和模式匹配通常没有数学有效性的概念——唯一关心的是表达式的结构形式。数学有效性的概念需要明确编程。例如,如果一个人想要一个应用于数学意义上的任何实数的函数,他会为这两个变量编写
f[x_/;x\[Element]Reals]:=…
@rcollyer:只是为了好玩,我试了一个微基准:
计时[Do[f[10],{10000000}]
<代码>/运行时间占
所需时间的75%。我不会对这个结果读太多。在Mathematica中,表现力和清晰度通常比性能更重要。我会继续写下上下文中最清晰的形式。工作中也有个人偏好——我碰巧用了“/;”很多YMMV。当性能是一个大问题时,人们可能会寻找不同的算法,或者,如果失败,使用
Compile
或符号C或其他东西。@reach原因可能是
条件的
FullForm
pattertest的
FullForm
使用
函数的
要简单得多:
f[x//x\[Element]Reals]//FullForm
f[x?(Element[#,Reals]&]//完整格式
。如果没有
函数
模式测试
稍微快一点:
ClearAll[f];f[x_?NumericQ]:=x;定时[Do[f[10],{20000000}]
ClearAll[f];f[x_/;NumericQ[x]]:=x;定时[Do[f[10],{20000000}]
。这证实了你的见解,即我们应该在上下文中写出最清晰的形式。这样的多个头匹配是非常脆弱的。很容易忘记一种类型的表达式,就像你在这里忘记了
Rational
,或者类似
Sqrt[2]
(不仅仅是
Pi
)。如果您需要检查表达式是否仅为数值表达式(而不是它是否有虚部),
x_?NumericQ
是最好的。@Szabolcs:我最初考虑的是
Rational
,因为我检查了它是否不包括复有理数,然后我放弃了