de-vraag
  • Вопросы
  • Метки
  • Пользователи
Оповещения
Вознаграждения
Регистрация
После регистрации, сможете получать уведомления об ответах и комментариях на Ваши вопросы.
Вход
Если у Вас уже есть аккаунт, войдите чтобы проверить новые уведомления.
Тут будут вознаграждения за добавленные вопросы, ответы и комментарий.
Дополнительно
Источник
Редактировать
Alejandro Ll.
Alejandro Ll.
Вопрос

Точность Matlab: простое вычитание не равно нулю

Я вычислил эту простую сумму на Matlab:

2*0.04-0.5*0.4^2 = -1.387778780781446e-017

но результат не равен нулю. Что я могу сделать?

1 2011-10-27T15:43:17+00:00 5
 Kara
Kara
Редактировал вопрос 14-го февраля 2014 в 9:11
Программирование
matlab
precision
floating-point
Sam Roberts
27-го октября 2011 в 4:16
2011-10-27T16:16:26+00:00
Дополнительно
Источник
Редактировать
#56790248

У Аабаза и Джима Клея есть хорошие объяснения того, что происходит.

It's often the case that, rather than exactly calculating the value of 2*0.04 - 0.5*0.4^2, what you really want is to check whether 2*0.04 and 0.5*0.4^2 differ by an amount that is small enough to be within the relevant numerical precision. If that's the case, than rather than checking whether 2*0.04 - 0.5*0.4^2 == 0, you can check whether abs(2*0.04 - 0.5*0.4^2) < thresh. Here thresh can either be some arbitrary smallish number, or an expression involving eps, which gives the precision of the numerical type you're working with.

РЕДАКТИРОВАТЬ: Спасибо Джим и Таль за предлагаемое улучшение. Изменено, чтобы сравнить абсолютное значение разности с порогом, а не разницу.

4
0
Jeffrey Sax
27-го октября 2011 в 4:41
2011-10-27T16:41:47+00:00
Дополнительно
Источник
Редактировать
#56790249

Matlab использует числа с плавающей запятой с двойной точностью для хранения реальных чисел. Это числа формы m * 2 ^ e , где m - целое число между 2 ^ 52 и 2 ^ 53 ( mantissa ) и e является показателем. Давайте назовем число числом с плавающей запятой, если оно имеет эту форму.

Все числа, используемые в вычислениях, должны быть числами с плавающей запятой. Часто это можно сделать точно, как в 2 и 0.5 в вашем выражении. Но для других чисел, в первую очередь большинства чисел с цифрами после десятичной точки, это невозможно, и нужно использовать аппроксимацию. Что происходит в этом случае, так это то, что число округлено до ближайшего числа с плавающей запятой.

So, whenever you write something like 0.04 in Matlab, you're really saying "Get me the floating-point number that is closest to 0.04. In your expression, there are 2 numbers that need to be approximated: 0.04 and 0.4.

Кроме того, точный результат операций, таких как сложение и умножение чисел с плавающей запятой, может не быть числом с плавающей запятой. Хотя он всегда имеет вид m * 2 ^ e , мантисса может быть слишком большой. Таким образом, вы получаете дополнительную ошибку от округления результатов операций.

В конце дня простое выражение, подобное вашему, будет примерно на 2 ^ -52 раза больше размера операндов или около 10 ^ -17.

Вкратце: причина, по которой ваше выражение не оценивается в ноль, двояка:

  1. Некоторые номера, с которых вы начинаете, отличаются (приближениями) к точным номерам, которые вы указали.
  2. Промежуточные результаты могут также быть приближением точных результатов.
2
0
Aabaz
27-го октября 2011 в 3:55
2011-10-27T15:55:57+00:00
Дополнительно
Источник
Редактировать
#56790245

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

Например:

a=0.04;
b=0.2;
a-0.2*b
ans=-6.9389e-018
c=a/min(abs([a b]));
d=b/min(abs([a b]));
c-0.2*d
ans=0

EDIT: of course I did not mean to give a universal solution to these kind of problems but it is still a good practice that can make you avoid a few problems in numerical computation (curve fitting, etc ...). See Jim Clay's answer for the reason why you are experiencing these problems.

1
0
Jim Clay
27-го октября 2011 в 4:04
2011-10-27T16:04:49+00:00
Дополнительно
Источник
Редактировать
#56790246

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

1
0
hex4def6
27-го октября 2011 в 4:13
2011-10-27T16:13:48+00:00
Дополнительно
Источник
Редактировать
#56790247

Я уверен, что это случай, когда вы стареете с точки зрения точности с плавающей запятой.

Вам нужна точность 1е-17? Это всего лишь случай желания «хорошенького» вывода? В этом случае вы можете просто использовать форматированный sprintf для отображения количества значимых цифр, которые вы хотите.

Поймите, что это не проблема Matlab, а фундаментальное ограничение того, как числа представлены в двоичном формате.

Для удовольствия, выработайте то, что .1 находится в двоичном формате ...

Некоторые ссылки: http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems http://www.mathworks.com/support/tech-notes/1100/1108.html

1
0
Добавить вопрос
Категории
Все
Технологий
Культура / Отдых
Жизнь / Искусство
Наука
Профессии
Бизнес
Пользователи
Все
Новые
Популярные
1
Roxana Elizabeth CASTILLO Avalos
Зарегистрирован 5 дней назад
2
Hideo Nakagawa
Зарегистрирован 5 дней назад
3
Sergiy Tytarenko
Зарегистрирован 1 неделю назад
4
shoxrux azadov
Зарегистрирован 1 неделю назад
5
Koreets Koreytsev
Зарегистрирован 1 неделю назад
© de-vraag 2022
Источник
stackoverflow.com
под лицензией cc by-sa 3.0 с атрибуцией