2008-10-30 4 views
25

Я слышал о «ошибке» при использовании переменных с плавающей запятой. Теперь я пытаюсь решить эту загадку, и я думаю, что получаю ошибку округления/с плавающей запятой. Поэтому я, наконец, собираюсь выяснить основы ошибки с плавающей запятой.Что такое простой пример ошибки с плавающей запятой/округлением?

Что такое простой пример ошибки с плавающей точкой/округлением (желательно на C++)?

Редактировать: Например, у меня есть событие, которое имеет вероятность p успеха. Я делаю это событие 10 раз (p не меняется, и все испытания независимы). Какова вероятность ровно двух успешных испытаний? У меня этот код закодирован как:

double p_2x_success = pow(1-p, (double)8) * pow(p, (double)2) * (double)choose(8, 2); 

Это возможность для ошибки с плавающей запятой?

+0

Я думаю, что вам действительно нужно это: [Что каждый ученый должен знать о арифметики с плавающей точкой] (http://docs.sun.com/source/ 806-3568/ncg_goldberg.html). – Patrick 2008-10-30 07:17:08

+0

Читайте это: http://blog.frama-c.com/index.php?post/2013/05/02/nearbyintf1 – 2013-05-03 19:09:13

ответ

9

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

Целые числа хранятся с самым правым битом, равным 1, и каждый бит влево является двойным (2,4,8, ...). Легко видеть, что это может хранить любое целое число до 2^n, где n - количество бит.

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

Таким образом, цифры, такие как 0,5 (1/2), просты в хранении, но не каждое число < 1 может быть создано путем добавления фиксированного количества долей формы 1/2, 1/4, 1/8, ...

Действительно простой пример: 0,1 или 1/10. Это можно сделать с помощью бесконечной серии (которую я действительно не могу потрудиться), но всякий раз, когда компьютер хранит 0,1, это не совсем такое количество, которое хранится.

Если у вас есть доступ к машине Unix, это легко увидеть это:.

Python 2.5.1 (r251:54863, Apr 15 2008, 22:57:26) 
[GCC 4.0.1 (Apple Inc. build 5465)] on darwin 
Type "help", "copyright", "credits" or "license" for more information. 
>>> 0.1 
0.10000000000000001 
>>> 

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

(Что касается вашего примера, 0.2 - это еще один из этих надоедливых чисел, которые нельзя сохранить в двоичном формате IEEE, но пока вы проверяете неравенства, а не равенства, например p < = 0.2, тогда вы будете в порядке .)

5

Простой C, который содержит ХТ меня некоторое время назад,

char *c = "90.1000"; 
double d = 0; 
sscanf(c,"%f",&d); 
printf("%0.4f",d); 

>> 90.0999 

Это был в функции, преобразованной углы в DMS радианы, которые не делали в предыдущем случае.

26
for(double d = 0; d != 0.3; d += 0.1); // never terminates 
19

картинка стоит тысячи слов - попробуйте нарисовать уравнение f(k):
enter image description here
и вы получите такой XY график (X и Y в логарифмическом масштабе).
enter image description here
Если компьютер может представлять 32-битные поплавки без ошибки округления, то для каждого k мы должны получить нуль. Но вместо этого ошибка увеличивается с большими значениями k из-за накопления ошибок с плавающей запятой.

hth!

3

Вот один, который поймал меня.

round(256.49999) == 256 
roundf(256.49999) == 257 

двойники и плавает ..

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