Реальные против чисел с плавающей запятой против денег

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

Это: panix.com/~arnow/brooklyn_college/diatribe.html

Moshe 29.08.2013 20:11
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
20
1
26 011
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

В числах с плавающей запятой используются двоичные дроби, и они не соответствуют в точности десятичным дробям.

Для денег лучше хранить количество центов как целое число или использовать десятичный тип числа. Например, Decimal (8,2) хранит 8 цифр, включая 2 десятичных знака (xxxxxx.xx), то есть с точностью до центов.

Я бы хотел, чтобы вы оба получили баллы за хороший ответ. Вместо хранения центов мы используем денежную ценность. Как вы думаете, это тоже хорошая практика?

Middletone 07.11.2008 22:48

Хранение центов - плохая новость. Финансовые учреждения часто используют дробные центы в расчетах, а иногда их также необходимо хранить. Однажды я был в проекте, где это возникло после того, как было развернуто приложение для хранения центов. Очень некрасиво.

MusiGenesis 07.11.2008 23:08

Просто примечание, разве Decimal (8,2) на самом деле не xxxxxx.xx вместо xxxxxxxx.xx? 8 в определении относится к общему количеству цифр до и после десятичной точки.

Giannis Paraskevopoulos 28.05.2016 16:00
Ответ принят как подходящий

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

Числа с плавающей запятой в компьютерах не представляют в точности десятичные дроби. Вместо этого они представляют фракции двоичный. Большинство дробных чисел не имеют точного представления в виде двоичной дроби, поэтому происходит некоторое округление. Когда такая округленная двоичная дробь переводится обратно в десятичную дробь, вы получаете описанный вами эффект.

Для хранения денежных значений базы данных SQL обычно предоставляют тип DECIMAL, в котором хранятся точные десятичные цифры. Этот формат немного менее эффективен для компьютеров, но он весьма полезен, если вы хотите избежать ошибок округления десятичных дробей.

На самом деле, компьютеры справляются с существенно медленнее (примерно в десять раз, в первую очередь из-за отсутствия поддержки оборудования), но медленность не имеет значения для большинства приложений, поскольку числовые операции далеки от узкого места.

crazy2be 06.08.2011 06:45

Числа с плавающей запятой не представляют в точности десятичные дроби немного. Реальные числа в реальной жизни также не представляют точно дроби немного. 1/2, например, может быть точно представлен в обеих системах.

axiac 13.09.2016 15:09

Вкратце, это примерно по той же причине, что треть не может быть точно выражена в десятичной системе. Взгляните на классическую статью Дэвида Голдберга «Что должен знать каждый компьютерный ученый об арифметике с плавающей запятой» для подробностей.

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

С другой стороны, некоторые системы хранят дробные числа в десятичном виде (например, типы данных SQL Server Decimal и Numeric, а также тип данных Oracle Number), и поэтому их внутреннее представление является точным для любого числа, которое является степенью 10. Но тогда числа, не являющиеся степенями десяти, не могут быть представлены точно.

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