Деньги TSQL, брошенные как float, округляют точность - PullRequest
0 голосов
/ 06 декабря 2010

У меня есть база данных, которая хранит суммы и отображается в виде таблицы.У меня есть сумма, которая вводится как 3 594 879,59, и когда я смотрю в виде таблицы, я получаю 3 594 880,00.

Тип SQL Money - это деньги по умолчанию, в SQL ничего не было сделано при создании таблицы для настройки типа Money.,В Linq я разыгрываю сумму в число с плавающей точкой?

Что вызывает это?Это происходит только на больших числах (например, я поставил 1,5 в БД и 1,5 показывает в сетке).

Ответы [ 2 ]

2 голосов
/ 06 декабря 2010

Приведите денежный тип SQL к десятичному типу CLR.Десятичное число - это числовой тип с плавающей запятой, который использует внутреннее представление base-10 и поэтому может представлять любое десятичное число в диапазоне без аппроксимации.

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

РЕДАКТИРОВАТЬ: Что касается "почему это происходит" - две причины.Во-первых, числа с плавающей точкой используют внутреннее представление base-2, в котором невозможно точно представить некоторые десятичные дроби.Во-вторых, причина того, что числа с плавающей точкой называются числами с плавающей точкой, состоит в том, что вместо использования фиксированной точности для целочисленной части и фиксированной точности для дробной части, они обеспечивают непрерывный компромисс между величиной и точностью.Числа, в которых неотъемлемая часть относительно мала - например, 1,5 - позволяют большей части внутреннего представления быть назначенной дробной части, и, таким образом, обеспечивают гораздо большую точность.Поскольку величина интегральной части увеличивается, биты, которые ранее использовались для точности, теперь необходимы для хранения большего целочисленного значения, и поэтому точность дробной части снижается.

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

1.0000000123

, но для больших значений у вас не так много дробной точностидоступно:

1234567890.2

Для получения подробной информации о том, как на самом деле работает , ознакомьтесь со стандартом IEEE 754 .

1 голос
/ 06 декабря 2010

Если в качестве места назначения используется стандартное 32-разрядное число с плавающей точкой, то вы получаете именно то, что должны. Попробуйте сохранить его как деньги или измените его на масштабированное целое число или 64-разрядное число с плавающей запятой двойной точности.

32-разрядное число с плавающей запятой имеет от шести до семи значащих цифр точности. 64-разрядные числа с плавающей точкой имеют точность до 16 цифр.

...