LINUX.ORG.RU

Ошибка в вычислениях maxima.

 


0

2

Недавно столкнулся со странным поведением maxima: при попытке вычислить некоторые элементарные вещи возникал странный ответ. Например: (%i1) 0.041959-0.050807; (%o1)- 0.0088479999999999

Версия 5.32.1.

Ответ на: комментарий от post-factum

В данном примере можно сосчитать и точное значение, в большинстве подобных случаев maxima так и поступает.

Karthago ★★
() автор топика
Ответ на: комментарий от post-factum

float(factor(..)) даёт удовлетворительный результат, но зачем такие сложности в вычислениях элементарщины? Нет ли какого-нибудь другого способа?

Karthago ★★
() автор топика
Ответ на: комментарий от post-factum

Не всё так гладко:

%i4) res2:[0.00775,0.008343,0.008848,0.009267,0.009594,0.009824,0.009957,0.009987,0.009927];
(%o4) [0.00775, 0.008343, 0.008848, 0.009267, 0.009594, 0.009824, 0.009957, 
                                                            0.009987, 0.009927]
(%i5) res3:makelist(float(factor(res2[x+1]-res2[x])),x,1,8);

rat: replaced 5.929999999999998E-4 by 593/1000000 = 5.93E-4

rat: replaced 5.050000000000002E-4 by 101/200000 = 5.05E-4

rat: replaced 4.1899999999999923E-4 by 419/1000000 = 4.19E-4

rat: replaced 3.270000000000009E-4 by 366931480/1122114617737 = 3.270000000000009E-4

rat: replaced 2.299999999999993E-4 by 3352176314/14574679626087 = 2.299999999999993E-4

rat: replaced 1.3300000000000117E-4 by 113632870/854382481203 = 1.3300000000000117E-4

rat: replaced 2.9999999999998778E-5 by 245865746/8195524866667 = 2.999999999999878E-5

rat: replaced -5.999999999999929E-5 by -1686367528/28106125466667 = -5.999999999999929E-5
(%o5) [5.93E-4, 5.05E-4, 4.19E-4, 3.270000000000009E-4, 2.2999999999999928E-4, 
          1.3300000000000117E-4, 2.9999999999998774E-5, - 5.999999999999929E-5]

Karthago ★★
() автор топика
Ответ на: комментарий от post-factum

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

aiqu6Ait ★★★★
()
Ответ на: комментарий от aiqu6Ait

нет, если одно из чисел в процессе вычисления попалось с плавающей запятой, то все дальнейшие вычисления будут с плавающей запятой.

anonymous
()
Ответ на: комментарий от anonymous

Это не панацея:

(%i4) res2:[0.009594,0.009824,0.009957,0.009987,0.009927];(%o4)         [0.009594, 0.009824, 0.009957, 0.009987, 0.009927]
(%i5) fpprintprec:8;
(%o5)                                  8
(%i6) res3:makelist(float(rat(res2[x+1]-res2[x])),x,1,4);

rat: replaced 2.29999999E-4 by 3352176314/14574679626087 = 2.29999999E-4

rat: replaced 1.33E-4 by 113632870/854382481203 = 1.33E-4

rat: replaced 2.99999999E-5 by 245865746/8195524866667 = 2.99999999E-5

rat: replaced -5.9999999E-5 by -1686367528/28106125466667 = -5.9999999E-5
(%o6)      [2.29999999E-4, 1.33E-4, 2.99999999E-5, - 5.99999999E-5]

Но если попробовать разные значения параметра fpprintprec, то может помочь:

(%i7) fpprintprec:6;
(%o7)                                  6
(%i8) res3:makelist(float(rat(res2[x+1]-res2[x])),x,1,4);

rat: replaced 2.3E-4 by 3352176314/14574679626087 = 2.3E-4

rat: replaced 1.33E-4 by 113632870/854382481203 = 1.33E-4

rat: replaced 3.0E-5 by 245865746/8195524866667 = 3.0E-5

rat: replaced -5.99999E-5 by -1686367528/28106125466667 = -5.99999E-5
(%o8)                 [2.3E-4, 1.33E-4, 3.0E-5, - 6.0E-5]

Karthago ★★
() автор топика
Ответ на: комментарий от aiqu6Ait

Накопал немного на эту тему вот здесь.

Для Ъ:

Скажем пару слов о приведении конечной десятичной записи чисел к рациональной. Конечная десятичная запись считается по определению приблизительной, что и понятно, т.к. при вычислениях самой Maxima такая запись может возникнуть исключительно при применении приближенных методов либо при ручном указании о переводе числа в десятичную запись из математической, в результате чего результат тоже, вероятнее всего, окажется приблизительным. Эта приблизительность учитывается и при переводе в рациональные числа, а ее уровень, то есть мера, на которую рациональное число при переводе может отклониться от конечной десятичной записи, регулируется переменной ratepsilon, равной по умолчанию 2.0e-8, т.е. 0.00000002. Если такое положение вещей вас не устраивает, вы можете убедить Maxima оставлять десятичную запись чисел как есть, установив в true значение флага keepfloat (по умолчанию он равен false).

Karthago ★★
() автор топика

Возник ещё один вопрос: есть ли способ запретить maxima использовать плавающую запятую?

Karthago ★★
() автор топика
Ответ на: комментарий от Karthago

numer:true , но если в выражении плавающая точка - таки переключается в режим с плавающей точкой.

Как вариант - вычисляй все символьно (напиши функцию, например), а потом подставляй числа (если надо)

aiqu6Ait ★★★★
()
Ответ на: комментарий от Karthago

есть ли способ запретить maxima использовать плавающую запятую?

Не пользуйся плавающей запятой, вместо 0.041959 пиши 41959/1000000. Чтобы не ломать пальцы, сделай функцию mil(x)=x/1000000

no-such-file ★★★★★
()

У меня к вам встречный вопрос. Если вы на вход подаете дроби в виде миллионных, то почему на выходе вы не округляете до миллионных, хотя бы?

no-such-file ★★★★★
()
Ответ на: комментарий от no-such-file

Насколько я помню, округление дробных чисел до определённого знака после запятой в стандарт maxima не входят. До целых точно есть.

Karthago ★★
() автор топика
Ответ на: комментарий от Karthago

запятой в стандарт maxima не входят

При чём тут стандарт? Если человек не в состоянии написать функцию округления, то ему не максиму нужно мучить, а учебник арифметики.

no-such-file ★★★★★
()
Ответ на: комментарий от no-such-file

Я не спорю, что округление можно сделать, но с каких это пор в CAS нужно руками писать такие элементарные функции? Это как минимум странно, даже если maxima и не заточена для численных расчётов.

Karthago ★★
() автор топика
Ответ на: комментарий от Karthago

но с каких это пор в CAS нужно руками писать такие элементарные функции?

Какие элементарные? Округление до нужного разряда? В какой CAS есть такая функция из коробки?

Такое никому не нужно т.к. всем понятны особенности вычислений на компе. Для того чтобы обеспечивать нужную точность есть переменная fpprec, для того чтобы не печатать мусор в конце чисел есть переменная fpprintprec.

Вас наверное удовлетворит fpprintprec:6

no-such-file ★★★★★
()
Последнее исправление: no-such-file (всего исправлений: 1)
Ответ на: комментарий от no-such-file

fpprintprec не всегда даёт удовлетворительный результат, хотя в большинстве случаев всё же помогает. Смотри мой пост выше.

Насчёт функции округления до определённого знака в CAS я, скорее всего, не прав, вспомнил про ПО для численных вычислений.

Karthago ★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.