Чтобы лучше понять, как ошибки округления накапливаются, и получить более глубокое представление о том, что Происходило на более низком уровне, вот небольшой explanantion:
я буду считать, что IEEE 754 двойной стандарт точности используется базовой программной/аппаратной , с режимом округления по умолчанию (от округлой до ближайшей четной).
1/5 может быть записан в основании 2 с рисунком повторяя бесконечно
0.00110011001100110011001100110011001100110011001100110011...
Но с плавающей точкой, то мантисса - начиная с наиболее значимыми 1 бит - должна быть округлена до конечного числа бит (53)
Так что есть небольшая ошибка округления при представлении 0.2 в двоичной системе:
0.0011001100110011001100110011001100110011001100110011010
Вернуться к десятичному представлению, эта ошибка округления соответствует с до небольшого избытка 0.000000000000000011102230246251565404236316680908203125 выше 1/5
Первая операция затем точна, поскольку 0,2 ± 0,2, как 2 * 0,2, и, таким образом, не вносит дополнительную погрешность, это как сдвигая точку фракции:
0.0011001100110011001100110011001100110011001100110011010
+ 0.0011001100110011001100110011001100110011001100110011010
---------------------------------------------------------
0.0110011001100110011001100110011001100110011001100110100
Но, конечно, избыток выше 2/5 удваивается 0.00000000000000002220446049250313080847263336181640625
Третья операция 0,2 + 0,2 + 0,2 приведет к этому двоичного числа
0.011001100110011001100110011001100110011001100110011010
+ 0.0011001100110011001100110011001100110011001100110011010
---------------------------------------------------------
0.1001100110011001100110011001100110011001100110011001110
Но, к сожалению, это требует 54 бит мантиссы (промежуток между ведущим 1 и задней 1), так что другой ошибки округления необходимо представить результат в виде двойной:
0.10011001100110011001100110011001100110011001100110100
Обратите внимание, что номер был закругленный верхний, так как по умолчанию поплавков округляется до ближайшего даже в случае идеального галстука. Мы уже имели ошибку избытком, так везло, последовательные ошибки сделал аккумулировать, а не аннулируют ...
Так избыток выше 3/5 теперь 0,000000000000000088817841970012523233890533447265625
Вы могли бы сократить немного в этом накопление ошибок, с использованием
x1 = i/5.0
так как 5 представлена именно в поплавка (101,0 в двоичной системе, 3 мантисса биты являются достаточно), и так как это также будет случай I (до 2^53), имеется один округление при выполнении разделения, а затем IEEE 754 гарантирует, что вы получите максимально возможное представление.
, например, 3/5.0 представлен как:
0.10011001100110011001100110011001100110011001100110011
Назад к десятичной, значение по умолчанию представлено 0.00000000000000002220446049250313080847263336181640625 под 3/5
Обратите внимание, что обе ошибки очень маленькие, но во втором случай 3/5.0, в четыре раза меньше по величине 0,2 + 0,2 + 0,2.
Привет и добро пожаловать в SO. Я думаю, что это поможет, если вы разместите свои попытки и почему они были неудовлетворительными, поэтому мы лучше понимаем, как вам помочь. – Tibos
Когда вы используете с плавающей запятой, вы должны признать, что в арифметике есть ошибки округления, и вы должны разработать свой код для работы с этим. Поскольку значение .6 не является точно представимым в двоичной с плавающей запятой, никакой код вообще не приведет к созданию двоичного объекта с плавающей запятой, имеющего точно значение .6. Вы должны признать, что будут ошибки. Вы не указали, какая проблема вызывает эти ценности. –
Тибос: Да, я, вероятно, должен был (в первый раз это сделал), возможно, я был одержим, пытаясь понять, как получить ровно 0,6. Эрик: Спасибо, что я не могу получить 0,6, помог мне изменить свой код и нарисовать реальную проблему. Что означало, что значение x1 использовалось при доступе к значению массива и в% == 0, в результате чего мои операторы if не запускались. Так что спасибо, я новичок в мире кодирования и stackoverflow, поэтому мне жаль, если я немного инструмент. – Ranth