如何在Mathematica中通过追加来重新定义一个函数?

3
在Mathematica中进行计算时,我经常需要通过添加来重新定义一个函数。例如,如果我定义了一个函数:
f[n_] := n^2 + n + 1

然后过一段时间,我想要添加 2n^3,从现在开始。

f[n] = 2n^3 + n^2 + n + 1. 

然后我想添加 Sin[n],并进一步进行操作。
f[n] = 2n^3 + n^2 + n + 1 + Sin[n]. 

等等。

对于变量来说,例如x += 2,这很容易做到。那么函数有没有类似的东西呢?…

编辑补充 - 是的,我在半手动地寻找最适合数据的函数。我知道有函数可以做到这一点,但我想看看自己能否达到这一点。我确实做到了,但做法并不优雅,所以才提出这个问题。


知道导致您想要添加术语的标准会非常有帮助。是因为不同的定义适用于不同的 n 值吗? - Verbeia
@Verbeia 看起来该 OP 只是试图选择一组适合在实验误差范围内拟合一些实验数据的基本函数组合。可能这是一个家庭作业。 - Alexey Popkov
@AlexeyPopkov - 是的,但为什么要混合使用多项式和三角函数基函数呢?我只是一个简单的经济学家,但这看起来很奇怪。 - Verbeia
1
如果已知实验数据包含(或可能包含)周期性和非周期性成分,使用多项式和三角函数的组合进行拟合是非常合理的。 @Verbeia - Alexey Popkov
1
@Alexey,以防你仍在手动操作 :) http://creativemachines.cornell.edu/eureqa - Dr. belisarius
5个回答

3

您的问题涉及到很多微妙的细节,我指的是非常微妙的细节。

我不会进入这个曲折的话题,但您可以尝试做以下事情:

f[n] = n^2;
f[n] = f[n] + 2
(* but for evaluation *)
f[n] /. n -> 2

因此,例如要绘制此图:
Plot[f[n] /. n -> x, {x, 0, 1}, AxesOrigin -> {0, 0}, 
                                PlotLabel  -> Framed@f[n]]

输入图像描述

然而,你不应该这样做。更多关于延迟定义的信息,请参阅延迟定义


3
你可以定义一个基函数列表,然后只需选择所需数量的元素即可:
fList = {n^2, n, 1, 2 n^3, Sin[n]}; 

f[n_] = Total[Take[fList, 3]]
f[n_] = Total[Take[fList, 4]]
f[n_] = Total[Take[fList, 5]]
(*
=> 1 + n + n^2
=> 1 + n + n^2 + 2 n^3
=> 1 + n + n^2 + 2 n^3 + Sin[n]
*)

我认为这对我的需求最好,因为如果需要的话,我可以添加到列表中。谢谢! - Dunda

3
一个晚来的解决方案:以下代码使用了一个辅助函数,并且为所有后续使用添加一个术语,您只需调用一次函数,并将第二个参数设置为表达所需添加术语的纯函数即可:
ClearAll[f];
Module[{g},
 g[n_] := n^2 + n + 1;
 f[n_, add_: Automatic] /; add === Automatic := g[n];
 f[n_, add_: Automatic] := Block[{m}, g[m] = g[m] + add[m]; g[n]];
]

使用示例:

In[43]:= f[m]
Out[43]= 1 + m + m^2

In[44]:= f[m, 2 #^3 &]
Out[44]= 1 + m + m^2 + 2 m^3

In[45]:= f[m]
Out[45]= 1 + m + m^2 + 2 m^3

In[46]:= f[m, Sin]
Out[46]= 1 + m + m^2 + 2 m^3 + Sin[m]

In[47]:= f[m]
Out[47]= 1 + m + m^2 + 2 m^3 + Sin[m]

采用这种方法时,你应该注意只在想要将术语添加到函数时调用两个参数形式,否则每次调用都会添加。


+1,我不感到惊讶你为此想出了一个简单而聪明的解决方案。 - rcollyer
1
@rcollyer花了我一些时间。实际上,在我看来,这更像是一个设计问题。感谢点赞。 - Leonid Shifrin

1

这个可以工作,但需要单独的函数。泛化追加函数并不容易。

Clear[f]
AppendToFunction := (
   a = DownValues[f];
   b = Append[a[[1, 2]], 2 n^3];
   f[n_] = Evaluate[b]);

AppendSinToFunction := (
   a = DownValues[f];
   b = Append[a[[1, 2]], Sin[n]];
   f[n_] = Evaluate[b]);

f[n_] := n^2 + n + 1;
f[3] == 9 + 4
DownValues[f]

(* 
->True
->{HoldPattern[f[n_]]:>n^2+n+1}
*)

AppendToFunction
f[3] == 9 + 4 + 54
DownValues[f]

(*
->1+n+n^2+2 n^3
->True
->{HoldPattern[f[n_]]:>1+n+n^2+2 n^3}
*)

AppendSinToFunction
f[3] == 9 + 4 + 54 + Sin[3]
DownValues[f]

(*
->1+n+n^2+2 n^3+Sin[n]
->True
->{HoldPattern[f[n_]]:>1+n+n^2+2 n^3+Sin[n]}
*)

1

这真的取决于你为什么需要重新定义函数f。如果原因是你意识到之前的定义是错误的,那么请回到相关单元格,进行编辑和重新评估以重新定义f

f[n_] := n^2 + n + 1

变成

f[n_] := 2n^3 + n^2 + n + 1 

请注意:=语法和下划线。
如果您希望f对于例如n<=100采用第一个定义,而对于n>100采用第二个定义,则可以使用Condition语法/;,如下所示。
f[n_] := n^2 + n + 1 /; n<=100
f[n_] := 2n^3 + n^2 + n + 1 /; n>100

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接