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}, ...]
我想为迈克的优秀答案添加一些东西.
首先,分号是构建复合表达式的方法,正如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向返回值Print是Null.
在他的评论中加入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声明,因为没有必要,l1a在If声明中设置.