Компьютерная точность: когда мне следует об этом беспокоиться?

В программировании на C ++, когда мне нужно беспокоиться о точности? Чтобы взять небольшой пример (хотя, возможно, он не идеален),

std::vector<double> first (50000, 0.0);
std::vector<double> second (first);

Возможно ли, что second[619] = 0.00000000000000000000000000001234 (Я имею ввиду очень маленькое значение). Или же SUM = second[0]+second[1]+...+second[49999] => 1e-31? Или же SUM = second[0]-second[1]-...-second[49999] => -7.987654321e-12?

Мои вопросы:

  1. Могут ли быть небольшие помехи в работе с double введите цифры?
  2. Что может вызвать такие мелкие нарушения? т.е. ошибки округления становятся большими? Не могли бы вы перечислить их? Как принять меры предосторожности?
  3. Если в определенных операциях могут быть небольшие помехи, значит ли это после этих операций, используя if (SUM == 0) является опасно? Нужно всегда использовать if (SUM < SMALL) вместо этого, где SMALL определяется как очень небольшое значение, такое как 1E-30?
  4. Наконец, могут ли небольшие помехи привести к отрицательному значению? Потому что если это возможно, то мне лучше использовать if (abs(SUM) < SMALL) вместо.

Есть опыт?

1

Решение

Это хороший справочный документ для точности с плавающей запятой: Что каждый компьютерщик должен знать об арифметике с плавающей точкой

Одна из наиболее важных частей — катастрофическая отмена

Катастрофическая отмена происходит, когда операнды
ошибки округления. Например, в квадратной формуле выражение
b2 — 4ac происходит. Величины b2 и 4ac подлежат округлению
ошибки, так как они являются результатом умножения с плавающей точкой.
Предположим, что они округлены до ближайшего числа с плавающей точкой,
и так с точностью до .5 ulp. Когда они вычитаются,
отмена может привести к исчезновению многих точных цифр,
оставляя в основном цифры, загрязненные ошибкой округления. Следовательно
Разница может иметь ошибку многих ульпов. Например, рассмотрим b =
3,34, а = 1,22 и с = 2,28. Точное значение b2 — 4ac составляет 0,0292. Но b2 округляет до 11,2 и 4ac округляет до 11,1, следовательно, окончательный ответ
равно .1, что является ошибкой на 70 ульпов, хотя 11.2 — 11.1 точно
равно .16. Вычитание не внесло никакой ошибки, а скорее
выявил ошибку, внесенную в более ранние умножения.

Доброкачественная отмена происходит при вычитании точно известных количеств.
Если x и y не имеют ошибки округления, то по теореме 2, если
вычитание делается с защитной цифрой, разница х-у очень
небольшая относительная погрешность (менее 2).

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

4

Другие решения

Для вашего конкретного примера 0 имеет точное представление в виде двойного числа, и добавление ровно 0 к двойному не меняет его значения.

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

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

1

По вопросам рекламы [email protected]