2013-05-02 1 views
1

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

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

Может быть, возможно, что second[619] = 0.000000000000000000000000000 (я имею в виду очень маленькое значение). Или 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).

Любые впечатления?

ответ

4

Это хороший справочный документ для точности с плавающей запятой: What Every Computer Scientist Should Know About Floating-Point Arithmetic

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

Катастрофическое сокращение происходит, когда операнды подлежат ошибки округления. Например, в квадратичной формуле имеет место выражение b2 - 4ac. Величины b2 и 4ac подвергаются округлению ошибок, поскольку они являются результатом умножения с плавающей запятой. Предположим, что они округлены до ближайшего числа с плавающей запятой, и поэтому точны с точностью до .5 ulp. При вычитании отмена может привести к исчезновению многих точных цифр, , оставляя в основном цифры, загрязненные ошибкой округления. Следовательно, разница может иметь ошибку многих ulps. Например, рассмотрим b = 3.34, a = 1.22 и c = 2.28. Точное значение b2 - 4ac равно 0,0292. Но b2 раундов до 11.2 и 4ac раундов до 11.1, поэтому окончательный ответ равен .1, что является ошибкой на 70 ulps, хотя 11.2 - 11.1 точно равна , равному 0,16. Вычитание не привело к какой-либо ошибке, но раскрыл ошибку, введенную в более ранние умножения.

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

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

1

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

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

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

Смежные вопросы