Модуль Mathematica не возвращает значение - PullRequest
7 голосов
/ 15 ноября 2011

Я новичок в 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 ]

10 голосов
/ 15 ноября 2011

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

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 <0, и + y в противном случае. Единственное исключение - это когда появляется <code>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}, ...]

8 голосов
/ 15 ноября 2011

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

Во-первых, точка с запятой - это способ построения составных выражений , и, как указал Майк, они подавляют вывод непосредственно предшествующего оператора. Но они наиболее полезны, позволяя вам объединять несколько выражений вместе, где ожидается только одно выражение, как в теле 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.

...