我是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];
我的目标是能够绘制和集成此功能。
答案 0 :(得分:10)
在你的街区中间你有:
If[Length[bounce1x] > 0,
bounce1x = bounce1x[[1]];,
bounce1x = offset;
]
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
];
否则,Mathematica会将其解释为该语句的乘法次数,无论下一次出现的是什么。在这种情况下,您将从null
语句返回If
,并将其乘以出现的下一个If
语句的返回值。
对于Module
,语法为:Module[{localvars}, ReturnValue]
这意味着返回没有分号的最后一个语句是ReturnValue。例如,以下模块:
Module[{y},
y = x * x;
If[x < 0, -y, +y]
]
当x Return
出现时。就像在大多数语言中一样,您可以使用Return
:从函数中提前返回
Module[{y},
y = x * x;
If[x < 0,
Return[-y],
Return[+y]];
(* We never reach this point to return null *)
];
关于你的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]
您应该注意的另一件事是您在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 *)
要避免这种情况,请在Module
的开头定义您用作局部变量的所有变量:Module[{a, b, c, d}, ...]
答案 1 :(得分:8)
我想向Mike's excellent answer添加一些内容。
首先,分号是构建compound expressions的方式,正如迈克指出的那样,它们会抑制前一个语句的输出。但是,它们最有用的是允许您将多个表达式链接在一起,只需要一个表达式,就像在Module
的正文中一样。但是,它们对于像这个人为的例子这样简单的事情很有用。
a = 5;
b = (Print[a]; a - 3)
请注意括号; ;
的优先级低于=
,因此
b = Print[a]; a - 3
会将b设置为Print
的返回值Null
。
将Sjoerd在评论中所说的内容纳入表达式
b = (Print[a]; a - 3)
被解释为
Set[b, CompoundExpression[ Print[a], a - 3] ]
而第二个不正确的表单被解释为
CompoundExpression[ Set[b, Print[a]], a - 3]
如果要查看表达式采用何种形式,请使用FullForm[Hold[ expression ]]
显示表达式的内部形式。在检查表单之前,如果不希望执行任何操作,则需要使用Hold
,Set
就是这种情况。
其次,当If
表达式Set
将变量用于不同的值时,可以将其从If
语句中拉出,如下所示
bounce1x = If[Length[bounce1x] > 0, bounce1x[[1]], offset];
由于If
将返回bounce1x[[1]]
或offset
。这可以大大简化您的表达。这也适用于SetDelayed
(:=
),就像panelSlope
panelSlope := If[x <= 0, N[panelCoeff], -N[panelCoeff]];
但是,我不会在这里使用SetDelayed
,因为每次使用时都不需要重新计算panelSlope
。此外,您可以使用UnitStep
,
panelSlope = (1 - 2 UnitStep[x]) N[panelCoeff];
或者,甚至
panelSlope = If[x<=0, 1, -1] N[panelCoeff];
(Sign
在这里不合适,因为当参数为0时它将返回零。)
最后,您的代码中存在与l1a
有关的错误。您的Module
会将其返回,但如果未满足bounce1x > -interval && bounce1x < interval
条件,则不会输入设置它的If
语句。因此,它会返回l1a$###
形式的内容,其中###
是数字。另外,我完全摆脱了Return[ l1a ]
语句中的If
,因为没有必要,l1a
语句中设置了If
。