Почему, когда я сохраняю значение, скажем, 40,54 в SQL Server, в столбце типа Real, оно возвращает мне значение, которое больше похоже на 40,53999878999 вместо 40,54? Я видел это несколько раз, но так и не понял, почему это происходит. Кто-нибудь еще сталкивался с этой проблемой, и если да, то вызывает ее?





В числах с плавающей запятой используются двоичные дроби, и они не соответствуют в точности десятичным дробям.
Для денег лучше хранить количество центов как целое число или использовать десятичный тип числа. Например, Decimal (8,2) хранит 8 цифр, включая 2 десятичных знака (xxxxxx.xx), то есть с точностью до центов.
Я бы хотел, чтобы вы оба получили баллы за хороший ответ. Вместо хранения центов мы используем денежную ценность. Как вы думаете, это тоже хорошая практика?
Хранение центов - плохая новость. Финансовые учреждения часто используют дробные центы в расчетах, а иногда их также необходимо хранить. Однажды я был в проекте, где это возникло после того, как было развернуто приложение для хранения центов. Очень некрасиво.
Просто примечание, разве Decimal (8,2) на самом деле не xxxxxx.xx вместо xxxxxxxx.xx? 8 в определении относится к общему количеству цифр до и после десятичной точки.
Взгляните на Что должен знать каждый компьютерный ученый об арифметике с плавающей запятой.
Числа с плавающей запятой в компьютерах не представляют в точности десятичные дроби. Вместо этого они представляют фракции двоичный. Большинство дробных чисел не имеют точного представления в виде двоичной дроби, поэтому происходит некоторое округление. Когда такая округленная двоичная дробь переводится обратно в десятичную дробь, вы получаете описанный вами эффект.
Для хранения денежных значений базы данных SQL обычно предоставляют тип DECIMAL, в котором хранятся точные десятичные цифры. Этот формат немного менее эффективен для компьютеров, но он весьма полезен, если вы хотите избежать ошибок округления десятичных дробей.
На самом деле, компьютеры справляются с существенно медленнее (примерно в десять раз, в первую очередь из-за отсутствия поддержки оборудования), но медленность не имеет значения для большинства приложений, поскольку числовые операции далеки от узкого места.
Числа с плавающей запятой не представляют в точности десятичные дроби немного. Реальные числа в реальной жизни также не представляют точно дроби немного. 1/2, например, может быть точно представлен в обеих системах.
Вкратце, это примерно по той же причине, что треть не может быть точно выражена в десятичной системе. Взгляните на классическую статью Дэвида Голдберга «Что должен знать каждый компьютерный ученый об арифметике с плавающей запятой» для подробностей.
Чтобы добавить пояснение, числа с плавающей запятой, хранящиеся на компьютере, ведут себя так, как описано в других сообщениях здесь, потому что, как описано, они хранятся в двоичном формате. Это означает, что если только его значение (как мантисса, так и компоненты экспоненты значения) не являются степенями двойки и не могут быть представлены точно.
С другой стороны, некоторые системы хранят дробные числа в десятичном виде (например, типы данных SQL Server Decimal и Numeric, а также тип данных Oracle Number), и поэтому их внутреннее представление является точным для любого числа, которое является степенью 10. Но тогда числа, не являющиеся степенями десяти, не могут быть представлены точно.
Это: panix.com/~arnow/brooklyn_college/diatribe.html