Почему этот код вызывает сбой машины? - PullRequest
0 голосов
/ 24 июля 2011

Я пытаюсь запустить этот код, но он продолжает падать:

log10(x):=log(x)/log(10);
char(x):=floor(log10(x))+1;
mantissa(x):=x/10**char(x);
chop(x,d):=(10**char(x))*(floor(mantissa(x)*(10**d))/(10**d));
rnd(x,d):=chop(x+5*10**(char(x)-d-1),d);
d:5;
a:10;
Ibwd:[[30,rnd(integrate((x**60)/(1+10*x^2),x,0,1),d)]];
for n from 30 thru 1 step -1 do Ibwd:append([[n-1,rnd(1/(2*n-1)-a*last(first(Ibwd)),d)]],Ibwd);

Сбой Maxima при оценке последней строки. Есть идеи, почему это может произойти?

Большое спасибо.

Ответы [ 3 ]

2 голосов
/ 28 июля 2011

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

for n from 30 thru 1 step -1 do
  block([],
    print (1/(2*n-1)-a*last(first(Ibwd))),
    print (a*last(first(Ibwd))),
    Ibwd: append([[n-1,rnd(1/(2*n-1)-a*last(first(Ibwd)),d)]],Ibwd),
    print (Ibwd));

Последнее различие, напечатанное до того, как все закончится неудачей - это -316539/6125000. Так что теперь попробуйте

rnd(-1,3)

и вижу ту же проблему. Все это связано с тем, что вы берете лог отрицательного числа, которое Maxima интерпретирует как комплексное число путем аналитического продолжения. Maxima не оценивает это до тех пор, пока это абсолютно не нужно, и где-то в коде оценки что-то ужасно умирает.

Я не знаю "исправления" для вашего конкретного примера, поскольку я не совсем уверен, что вы пытаетесь сделать, но, надеюсь, это даст вам достаточно информации, чтобы найти его самостоятельно.

1 голос
/ 31 июля 2011

Похоже, что ваша программа вызывает ошибку в коде упрощения (алгебраических тождеств) Maxima.Мы расследуем, и я надеюсь, что у нас скоро исправление ошибки.

А пока вот идея.Похоже, ошибка вызвана rnd (x, d), когда x <0. Я предполагаю, что rnd должен округлять цифры от x до d.Чтобы обработать x <0, попробуйте это: </p>

rnd (x, d): = если x <0, то -rnd1 (-x, d) иначе rnd1 (x, d); </p>

rnd1 (x, d): = (... поместите здесь текущее определение rnd ...);

Когда я это делаю, цикл запускается до конца, и Ibwd представляет собой список значений, но яне знаю, какие значения ожидать.

1 голос
/ 28 июля 2011

Если вы хотите деконструировать число с плавающей запятой, давайте сначала удостоверимся, что это большое число. скажем z: 34.1

Вы можете получить доступ к частям большого плавания с помощью lisp, а также вы можете получить доступ к длине мантиссы в битах с помощью ?fpprec.

Таким образом ?second(z)*2^(?third(z)-?fpprec) дает вам:

4799148352916685/140737488355328

и bfloat(%) дает вам:

3.41b1.

Если вы хотите, чтобы мантисса z была целым числом, посмотрите на ?second(z) Теперь я не уверен, что вы пытаетесь достичь в базе 10, но Максима не выполняет внутреннюю арифметику в базе 10.
Если вы хотите больше или меньше битов, вы можете установить fpprec, который связан с ?fpprec. fpprec - это «приблизительная базовая 10» точность. Таким образом, fpprec изначально 16 ?fpprec соответственно 56.

Вы можете легко изменить их оба, например, fpprec: 100 соответствует ?fpprec из 335.

Если вы возитесь с представлениями с плавающей точкой, вам может быть полезно знать что вы можете посмотреть на любой из списков, набрав, например, ?print(z)

, которая печатает внутреннюю форму, используя функцию печати Lisp.

Вы также можете отследить любую функцию, вашу или системную. Например, вы можете рассмотреть возможность сделать это:

trace(append,rnd,integrate);

Если вы хотите использовать машинные поплавки, я предлагаю вам использовать для последней строки

для n с 30 по 1 шаг -1 выполните:

Ibwd:append([[n-1,rnd(1/(2.0*n- 1.0)-a*last(first(Ibwd)),d)]],Ibwd);

Обратите внимание на десятичные точки. Но даже этого не достаточно, потому что интеграция вставляет точные структуры, такие как atan (10). Попытка округлить эти вещи, или вычислить журнал из них, вероятно, не то, что вы хотите сделать. Я подозреваю, что Maxima недовольна, потому что журналу дается какое-то грязное выражение, которое оказывается отрицательным, хотя изначально оно считало иначе. Он передает номер программе регистрации lisp, которая с радостью возвращает соответствующий объект комплексного числа Common-lisp. К сожалению, большая часть Maxima была написана ДО того, как LISP имели сложные номера.

Таким образом, результат (log -0.5)= #C(-0.6931472 3.1415927) совершенно неожидан для остальной части Maxima. Максима имеет свою форму для комплексных чисел, например, 3+4*%i.

В частности, программа отображения Maxima предшествует общему формату комплексных чисел lisp и не знает, что с ним делать.

Ошибка (переполнение стека !!!) из программы дисплея, пытающейся отобразить общее комплексное число lisp.

Как все это исправить? Ну, вы можете попробовать изменить свою программу, чтобы она вычисляла то, что вы действительно хотите, и в этом случае она, вероятно, не вызовет эту ошибку. Программа отображения Maxima тоже должна быть исправлена. Кроме того, я подозреваю, что есть кое-что неудачное в упрощении журналов чисел, которые являются отрицательными, но не очевидно так.

Возможно, это слишком много информации для оригинального плаката, но, возможно, параграф выше поможет, а также, возможно, улучшит Maxima в одном или нескольких местах.

...