Модуль Mathematica Не Возвращает Значение

Я новичок в Mathematica и использую модуль для выполнения процедуры, а затем возвращаю значение. Однако 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];

моя цель состоит в том, чтобы иметь возможность графически и интегрировать эту функцию.

2 ответов


в середине вашего блока у вас есть:

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]
]

возвратит-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}, ...]


я хотел бы добавить пару вещей в отличный ответ Майка.

во-первых, полуколоны-это способ построения сложные выражения, и, как указал Майк, они подавляют вывод непосредственно предшествующего утверждения. Но они наиболее полезны, позволяя вам связывать несколько выражений вместе, где ожидается только одно выражение, например, в теле Module, как вы делаете. Тем не менее, они полезны для более простых вещей такой пример

a = 5;
b = (Print[a]; a - 3)

обратите внимание на скобки;; имеет более низкий приоритет, чем =, так что

b = Print[a]; a - 3

установит b в возвращаемое значение Print что это Null.

чтобы включить то, что говорил Шьерд в своем комментарии, выражение

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 заявление.