(int)(33.46639 * 1000000)
возвраты 33466389
Почему это происходит?
Математика с плавающей запятой не идеальна. Что должен знать каждый программист об этом.
Многие люди считают арифметику с плавающей точкой эзотерикой. Это довольно удивительно, потому что числа с плавающей запятой широко используются в компьютерных системах. Почти каждый язык имеет тип данных с плавающей запятой; компьютеры от ПК до суперкомпьютеров имеют ускорители с плавающей запятой; большинству компиляторов будет время от времени приходиться компилировать алгоритмы с плавающей запятой; и практически каждая операционная система должна реагировать на исключения с плавающей запятой, такие как переполнение. Эта статья представляет собой учебное пособие по тем аспектам операций с плавающей запятой, которые оказывают непосредственное влияние на разработчиков компьютерных систем. Он начинается с общих сведений о представлении с плавающей запятой и ошибке округления, продолжается обсуждением стандарта IEEE с плавающей запятой и заканчивается многочисленными примерами того, как сборщики компьютеров могут лучше поддерживать числа с плавающей запятой.
...
Сжатие бесконечного числа действительных чисел в конечное число битов требует приближенного представления. Хотя целых чисел бесконечно много, в большинстве программ результат целочисленных вычислений может храниться в 32-битном формате. Напротив, при любом фиксированном количестве битов большинство вычислений с действительными числами будут производить величины, которые невозможно точно представить с помощью такого количества битов. Поэтому результат вычисления с плавающей запятой часто должен округляться, чтобы снова уместиться в его конечном представлении. Эта ошибка округления является характерной чертой вычислений с плавающей запятой.
Если вы спрашиваете, почему это не становится 33466390
, потому что double
s не имеют бесконечной точности, и число не может быть точно выражено в двоичном формате.
Если заменить double
десятичным
( (int) (33,46639m * 1000000)
), он будет равен 33466390
, потому что десятичные
s вычисляются по основанию 10.
Причина, по которой вы получили другой результат, заключается в том, что вы использовали ' преобразование '
(int)(33.46639 * 1000000) returns 33466389 ^^^^^
, чтобы преобразовать результат в тип 'int' ... который округляется в большую или меньшую сторону от целочисленного типа при умножении и последующем преобразовании в 'int' .... не полагайтесь на числа с плавающей запятой, чтобы быть достаточно точным ... Скит опубликовал отличное введение на его сайте здесь и здесь ...
Причина в том, что 33,46639 будет представлено как нечто немного меньшее, чем это число.
Умножение на 1000000 даст вам 33466389,99999999.
Приведение типов с использованием (int) тогда просто вернет целую часть (33466389).
Если вам нужен «правильный» номер, попробуйте round () перед приведением типа.
Двойная точность не является точной, поэтому внутри 33.46639 фактически хранится как 33.466389
Изменить: как сказал Ричард, это данные с плавающей запятой (хранятся в двоичном формате в конечном наборе битов), так что это не совсем то) ....
В конце 1994 года был канун Нового года. Энди Гроув, генеральный директор Intel, выходил отличным годом, учитывая, что процессор Pentium вышел и стал большим ударить. Итак, он вошел в бар и заказал двойную порцию Johnnie Walker Green Label.
Бармен подал его и сказал: «Это будет 20 долларов, сэр».
Гроув положил двадцатидолларовую купюру на прилавок, взглянул на нее на мгновение и сказал: «Оставьте сдачу себе».
Потому что 33.46639 не может быть выражено точно конечным числом двоичных цифр. Фактический результат 33,46639 * 1000000: 33466389,9999999962747097015380859375. Приведение усекает его до 33466389.