Приведение float к десятичной дроби теряет точность в C # - PullRequest
5 голосов
/ 27 ноября 2011

В C # 4.0 следующее приведение ведет себя очень неожиданно:

(decimal)1056964.63f
1056965

Преобразование в удвоение работает просто отлично:

(double)1056964.63f
1056964.625

(decimal)(double)1056964.63f
1056964.625

Это по замыслу?

Ответы [ 2 ]

10 голосов
/ 27 ноября 2011

Проблема с вашим начальным значением - float в любом случае точна только до 7 значащих десятичных цифр:

float f = 1056964.63f;
Console.WriteLine(f); // Prints 1056965

Так что на самом деле пример second является неожиданным в некоторыхпутей.

Теперь значение точное в f равно 1056965,625, но это значение, заданное для всех значений от 1056964,563 до 1056964,687 - так что даже часть ".6" невсегда правильно.Вот почему документы для состояния System.Single:

По умолчанию значение Single содержит только 7 десятичных цифр точности, хотя внутренне поддерживается максимум 9 цифр.

Дополнительная информация по-прежнему сохраняется при преобразовании в double, потому что это может сохранить ее, вообще не «интерпретируя» ее - где преобразование в десятичную форму (для печати или для типа decimal) проходиткод, который знает, что он не может "доверять" этим двум последним цифрам.

0 голосов
/ 27 ноября 2011

Это по замыслу. Float может содержать ваше число [ edit ] довольно точно [ / edit ], но для целей преобразования его округляют до ближайшего целого числа, потому что между вашими значениями с плавающей точкой мало представимых значений число и целое число (1056964,75 и 1056964,88). См. COMNumber :: FormatSingle и COMDecimal :: InitSingle из SSCLI.

...