Mathematica模块没有返回值

Gee*_*irl 7 wolfram-mathematica module mathematical-optimization

我是Mathematica的新手,并使用Module执行过程,然后返回一个值.但是,Mathematica似乎正在评估和返回符号值而不是我想要的数值.

我的问题是:你什么时候不用分号?什么时候使用Return [value]而不是只写"value"?

DumpVar[x_] := Print[ToString[HoldForm[x]], ":", x];
SetAttributes[DumpVar, {Listable, HoldAll}]

width = 1;
interval = width/2;

panelCoeff = 2;
lightAngle = Pi/3;

(*Panel and light equations*)

panel[x_] = Abs[panelCoeff x];(*panelCoeff ((x)^2);*)

light[x_] = Tan[lightAngle]*x;

getAngleAttack[offset_] := 
  Module[{bounce1x, l1a, lightSlope, panelSlope},
   light[x_] = light'[x] (x - offset) + panel[interval];
   DumpVar[offset];

   lightSlope = N[light'[offset]];
   u1S = light'[offset];
   u1[x_] = (u1S (x - offset)) + panel[interval]; 

   bounce1x = 
    x /. N[NSolve[u1[x] == panel[x] && x < interval && x > -interval, 
       x]];

   u1r[x_] = panel'[bounce1x] (x - bounce1x) + panel[bounce1x];

   If[Length[bounce1x] > 0,
     bounce1x = bounce1x[[1]];,
     bounce1x = offset;
     ]

    If[bounce1x > -interval && bounce1x < interval,

     lightSlope = N[u1'[bounce1x]];

     If[x <= 0,
      panelSlope := N[panelCoeff],
      panelSlope := -N[panelCoeff]];

     DumpVar[lightSlope];
     DumpVar[panelSlope];
     l1a = 
      N[ArcTan[(lightSlope - 
           panelSlope)/(1 + (panelSlope lightSlope))]];

     DumpVar[l1a];

     l1a
      Return[l1a]
     ]

    Return[l1a];
   ];


myint = getAngleAttack[0];
(*myint = N[f[10]];*)
DumpVar[myint];

Plot[{panel[x], light[x]}, {x, -.6, .6}]

myint = getAngleAttack[.5];
DumpVar[myint];
Run Code Online (Sandbox Code Playgroud)

我的目标是能够绘制和集成此功能.

Mik*_*ley 10

在你的街区中间你有:

If[Length[bounce1x] > 0,
  bounce1x = bounce1x[[1]];,
  bounce1x = offset;
  ]
Run Code Online (Sandbox Code Playgroud)

格式If如下:If[Condition, ValueIfTrue, ValueIfFalse]

所以If[True, 3, 2]返回3,然后If[False, 3, 2]返回2.这里的分号是不必要的,但是你需要在if语句的末尾加一个分号:

If[Length[bounce1x] > 0,
  bounce1x = bounce1x[[1]],
  bounce1x = offset
  ];
Run Code Online (Sandbox Code Playgroud)

否则,Mathematica会将其解释为该语句的乘法次数,无论下一个要显示的是什么.在这种情况下,您null将从该If语句返回,并将其乘以下一个If语句的返回值.

对于Module语法是:Module[{localvars}, ReturnValue]

这意味着返回没有分号的最后一个语句是ReturnValue.例如,以下模块:

Module[{y},
   y = x * x;
   If[x < 0, -y, +y]
]
Run Code Online (Sandbox Code Playgroud)

当x <0时将返回-y,否则返回+ y.这是出现时的一个例外Return.就像在大多数语言中一样,您可以使用Return以下命令从函数中提前返回:

Module[{y},
   y = x * x;
   If[x < 0, 
      Return[-y],
      Return[+y]];
 (* We never reach this point to return null *)
 ];
Run Code Online (Sandbox Code Playgroud)

关于你Module,我认为这可能是你想要完成的事情:

getAngleAttack[offset_] := 
 Module[{bounce1x, l1a, lightSlope, panelSlope}, 
  light[x_] = light'[x] (x - offset) + panel[interval];
  DumpVar[offset];

  lightSlope = N[light'[offset]];
  u1S = light'[offset];
  u1[x_] = (u1S (x - offset)) + panel[interval];

  bounce1x = 
   x /. N[NSolve[u1[x] == panel[x] && x < interval && x > -interval, 
      x]];

  u1r[x_] = panel'[bounce1x] (x - bounce1x) + panel[bounce1x];

  If[Length[bounce1x] > 0,
   bounce1x = bounce1x[[1]],
   bounce1x = offset];

   If[bounce1x > -interval && bounce1x < interval,

   lightSlope = N[u1'[bounce1x]];

   If[x <= 0,
    panelSlope := N[panelCoeff],
    panelSlope := -N[panelCoeff]];

   DumpVar[lightSlope];
   DumpVar[panelSlope];

   l1a = N[
     ArcTan[(lightSlope - panelSlope)/(1 + (panelSlope lightSlope))]];

   DumpVar[l1a];
   Return[l1a]
  ];
  l1a]
Run Code Online (Sandbox Code Playgroud)

你应该注意的另一件事是你在一个内部使用的任何变量Module.如果您运行以下代码,您将获得4, -113/5, 32输出值:

d = 4 (* d was 4 *)
Module[{a, b, c},
   a = 3;
   b = 2;
   c = 5;
   d = 32; (* Uh oh! I just overwrite whatever d was *)
   a^2 + b / c - d]
d (* d is now 32 *)
Run Code Online (Sandbox Code Playgroud)

要避免这种情况,请在以下位置的开头定义您用作局部变量的任何变量Module:Module[{a, b, c, d}, ...]

  • @Geekgirl也许现在是告诉';'的好时机 实际上 - 就像Mathematic中的其他所有东西一样.在本例中,函数`CompoundExpression`,其中`a; b`等效于`CompoundExpression [a,b]`和`a; b;`等效于`CompoundExpression [a,b,Null]` (3认同)

rco*_*yer 8

我想为迈克的优秀答案添加一些东西.

首先,分号是构建复合表达式的方法,正如Mike指出的那样,它们会抑制前一个语句的输出.但是,它们最有用的是允许您将多个表达式链接在一起,只需要一个表达式,就像在a的主体中一样Module,就像你正在做的那样.但是,它们对于像这个人为的例子这样简单的东西很有用

a = 5;
b = (Print[a]; a - 3)
Run Code Online (Sandbox Code Playgroud)

注意括号; ;优先级低于=,所以

b = Print[a]; a - 3
Run Code Online (Sandbox Code Playgroud)

将设置B向返回值PrintNull.

在他的评论中加入Sjoerd所说的内容

b = (Print[a]; a - 3)
Run Code Online (Sandbox Code Playgroud)

被解释为

Set[b, CompoundExpression[ Print[a], a - 3] ]
Run Code Online (Sandbox Code Playgroud)

而第二个不正确的形式被解释为

CompoundExpression[ Set[b, Print[a]], a - 3]
Run Code Online (Sandbox Code Playgroud)

如果要查看表达式采用的形式,请使用FullForm[Hold[ expression ]]它来显示表达式的内部形式.Hold当您在检查表单之前不希望执行任何操作时,您需要使用,就像这样Set.

其次,当将变量的If表达式用于Set不同的值时,可以将其从If语句中拉出,如下所示

 bounce1x = If[Length[bounce1x] > 0, bounce1x[[1]], offset];
Run Code Online (Sandbox Code Playgroud)

因为If将返回bounce1x[[1]]offset.这可以大大简化您的表达.这也适用于SetDelayed(:=),就像panelSlope

panelSlope := If[x <= 0, N[panelCoeff], -N[panelCoeff]];
Run Code Online (Sandbox Code Playgroud)

但是,我不会SetDelayed在这里使用,因为panelSlope每次使用它都不需要重新计算.此外,你可以通过使用简化一点UnitStep,

panelSlope = (1 - 2 UnitStep[x]) N[panelCoeff];
Run Code Online (Sandbox Code Playgroud)

甚至

panelSlope = If[x<=0, 1, -1] N[panelCoeff];
Run Code Online (Sandbox Code Playgroud)

(Sign这里不合适,因为当参数为0时它将返回零.)

最后,您的代码中存在一个错误l1a.您Module将返回它,但如果bounce1x > -interval && bounce1x < interval不满足条件,If则不会输入设置它的语句.因此,它会返回形式的东西l1a$###哪里###是数字.此外,我完全摆脱了Return[ l1a ]If声明,因为没有必要,l1aIf声明中设置.