Вопрос

(int)(33.46639 * 1000000) ВОЗВРАТ 33466389

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

Это было полезно?

Решение

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

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

...

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

Другие советы

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

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

Это был канун Нового года в конце 1994 года.Энди Гроув, генеральный директор Intel, заканчивал отличный год, выпустив процессор Pentium, который стал большим хитом.Итак, он зашел в бар и заказал двойную порцию Johnnie Walker Green Label.

Бармен подал его и сказал: "С вас 20 долларов, сэр".

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

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

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

Умножение на 1000000 даст вам 33466389,99999999.

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

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

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

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

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

Причина, по которой вы получили другой результат, заключается в том, что вы использовали 'бросок'

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top