Подтвердить что ты не робот

Почему (int) (33.46639 * 1000000) возвращается 33466389?

(int)(33.46639 * 1000000) возвращает 33466389

Почему это происходит?

4b9b3361

Ответ 1

Математика с плавающей точкой не идеальна. Что каждый программист должен знать об этом.

Арифметика с плавающей точкой рассматривается многими эзотерическими субъектами. Это довольно удивительно, потому что плавающая точка вездесуща в компьютерных системах. Почти каждый язык имеет тип данных с плавающей запятой; компьютеры от ПК до суперкомпьютеров имеют ускорители с плавающей запятой; большинство компиляторов будут вынуждены время от времени компилировать алгоритмы с плавающей запятой; и практически каждая операционная система должна реагировать на исключения с плавающей запятой, такие как переполнение. В этом документе представлен учебник по тем аспектам с плавающей точкой, которые оказывают непосредственное влияние на разработчиков компьютерных систем. Он начинается с фона по представлению с плавающей запятой и ошибки округления, продолжается с обсуждением стандарта с плавающей запятой IEEE и заканчивается многочисленными примерами того, как сборщики компьютеров могут лучше поддерживать плавающие точки.

...

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

Ответ 2

Двойная точность не является точной, поэтому внутренне 33.46639 фактически хранится как 33.466389

Изменить: как сказал Ричард, данные с плавающей запятой (хранятся в двоичном виде в конечном наборе бит), так что это не совсем так)....

Ответ 3

Это был канун Нового года в конце 1994 года. Энди Гроув, генеральный директор Intel, близок к тому, что процессор Pentium выходит и становится большим хитом. Итак, он вошел в бар и заказал двойной снимок "Яркий ярлык" Джонни Уокера.

Бармен обслужил его и сказал: "Это будет 20 долларов США, сэр".

Гроув поставил счетчик на двадцать долларов на счетчик, посмотрел на него на мгновение и сказал: "Сохраните изменения".

http://en.wikipedia.org/wiki/Pentium_FDIV_bug

Ответ 4

Причина в том, что 33.46639 будет представлен как нечто немного меньшее, чем это число.

Умножение на 1000000 даст вам 33466389.99999999.

Тип-литье с использованием (int) просто вернет целочисленную часть (33466389).

Если вы хотите "правильное" число, попробуйте round() перед тем, как накладывать тип.

Ответ 5

Если вы спрашиваете, почему он не стал 33466390, это потому, что double не имеет бесконечной точности, и число не может быть точно выражено в двоичном формате.

Если вы замените double на decimal ((int)(33.46639m * 1000000)), он будет равен 33466390, потому что decimal вычисляются в базе 10.

Ответ 6

Потому что 33.46639 не может быть точно выражен в конечном числе двоичных цифр. Фактический результат 33.46639 * 1000000 - 33466389.9999999962747097015380859375. Литье усекает его до 33466389.

Ответ 7

Причина, по которой вы получили другой результат, - это то, что вы использовали "cast"

(int)(33.46639 * 1000000) returns 33466389
^^^^^

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