Mathematica中的动态,无需重复代码

时间:2012-02-12 13:06:03

标签: wolfram-mathematica

我正在尝试创建三个单独的图表,这段代码会给你一个想法:

f[t_] := Sin[10 t] + Cos[15 t];
Slider[Dynamic[dx], {0.01, 1}]
var = Dynamic[Fourier[Table[f[t], {t, 0, 100, dx}]]];
ListLinePlot[Abs[var]]
ListLinePlot[Re[var]]
ListLinePlot[Im[var]]

这不起作用,因为var尚未被评估,因此ListLinePlot / Abs / Re / Im不会将其识别为数字列表。 Dynamic必须包装ListLinePlot。

使用Dynamic包装ListLinePlot和其他所有内容。但后来我必须计算傅里叶[表格[...每个图表一次。按照原则,我不希望有这种重复的代码。

这是一种避免重复代码的方法,但不像我上面提到的不工作的例子那样具有语义,而且它将所有系列放在一个图形而不是三个单独的图形中:

Dynamic[
 ListLinePlot[
  (#[Fourier[
       Table[f[t], {t, 0, 100, dx}]
       ]]) & /@ {Abs,Re,Min}, DataRange -> {0, 100}
  ]
 ]

希望您现在可以看到我想要实现的目标。像我的第一段代码,除了它应该工作。我怎么能这样做?

3 个答案:

答案 0 :(得分:4)

在大多数情况下,您只需要在需要重新计算的表达式周围包裹Dynamic。正如您所注意到的,如果您将Dynamic包裹在var的内容周围,那么它将无效,因为ListPlot会在您通过{Dynamic时看到var头,而不是列表{1}}。在这种情况下需要重新计算的是完整的ListPlot

正确的解决方案是使用var的延迟定义(即:=而不是=)并将Dynamic包裹在ListPlot周围:

f[t_] := Sin[10 t] + Cos[15 t];
Slider[Dynamic[dx], {0.01, 1}]

var := Fourier[Table[f[t], {t, 0, 100, dx}]];

Dynamic@ListLinePlot[Abs[var]]
Dynamic@ListLinePlot[Re[var]]
Dynamic@ListLinePlot[Im[var]]

人们常常对Dynamic感到困惑,因为它有时会出现在表达式的深处,例如在您的Slider示例中。但Dynamic具有不同的功能:设置值。

通常,除非用于设置值,否则Dynamic始终需要是表达式中最外层的头部。 (有一些例外,特别是当我们处理表达式直接对应于屏幕上显示的内容,并由前端处理时,例如图形基元:Slider[Dynamic[x], {0, 5}],{ {1}}将有效。)

Graphics[{Disk[], Dynamic@Disk[{x, 0}]}]仅影响表达式在前端显示的方式,而不影响内核看到它们的方式。这是一个例子:

Dynamic

前端会将x=1 arr = {Dynamic[x], 2, 3} 显示为arr,但内核仍将其视为{1, 2, 3}。因此,如果我们计算{Dynamic[x], 2, 3},前端会将其显示为Total[arr],但内核会将其显示为1 + 5。我希望这能澄清一下情况。

注意:我不想在此解决方案中使用Dynamic[x] + 5,因为OP也没有使用它。 Manipulate只是一个高级便利功能,它可以通过Manipulate和一些控件(例如Dynamic)来实现。

答案 1 :(得分:2)

你可能想要这样的东西:

f[t_] := Sin[10 t] + Cos[15 t]

DynamicModule[{var},
 Manipulate[
  var = Fourier[Table[f[t], {t, 0, 100, dx}]];
  {ListLinePlot[Abs[var]],
   ListLinePlot[Re[var]],
   ListLinePlot[Im[var]]},
  {dx, 0.01, 1}
]]

Mathematica graphics

答案 2 :(得分:0)

未测试:

f[t_] := Sin[10 t] + Cos[15 t];
Slider[Dynamic[dx], {0.01, 1}]
Dynamic[var = Fourier[Table[f[t], {t, 0, 100, dx}]]];
Dynamic[ListLinePlot[Abs[var]]]
Dynamic[ListLinePlot[Re[var]]]
Dynamic[ListLinePlot[Im[var]]]

我认为这应该只计算一次Fourier。根据我的理解,ListLinePlot应该在评估Fourier后由var的变化触发(请注意var的分配 {{1} }})。