Приведение двойного к длинному изменяет значение - PullRequest
2 голосов
/ 08 октября 2019

Я заметил, что преобразование с double на long меняет значение , когда число для преобразования большое , даже если оно значительно ниже максимальное значение из long. Например, может кто-нибудь объяснить мне, почему это преобразование не работает должным образом :

Convert.ToInt64(600000000000040000d)
// Return => 600000000000039936
Convert.ToInt64(600000000000040000L)
// Return => 600000000000040000

Это вызывает некоторые проблемы в моих формулах ... Спасибо.

Ответы [ 2 ]

4 голосов
/ 08 октября 2019

Ну, double имеет мантисса из 52 бит только (подробности см. https://en.wikipedia.org/wiki/Double-precision_floating-point_format);поэтому double может представлять точные целочисленные значения вплоть до 2**53 - 1 == 9007199254740991. Однако

 600000000000040000 > 9007199254740991

, поэтому ошибки округления неизбежны:

  double d = 600000000000040000d;

  long l = (long)d;

  double d2 = l;

  Console.WriteLine($"{d:r} : {l} : ({d == d2 ? "Equal" : "Different"})");

Результат:

  6.0000000000004E+17 : 600000000000039936 : Equal

Можно попробовать decimalвместо double (особенно если вы работаете с финансовыми данными):

  decimal d = 600000000000040000m; // m suffix

  long l = (long)d;

  decimal d2 = l;

  Console.WriteLine($"{d} : {l} : ({d == d2 ? "Equal" : "Different"})");

Результат:

  600000000000040000 : 600000000000040000 : Equal
1 голос
/ 08 октября 2019

Надеюсь, это поможет:

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

Источник: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/explicit-numeric-conversions-table

Примечание: длинныйэто целочисленный тип, это Int64: В C # В чем разница между Int64 и long?

Кроме того, типы с плавающей точкой и double являются типами с плавающей точкой. Они хранятся в памяти по-разному Как числа с плавающей запятой хранятся в памяти?

Википедия: https://en.wikipedia.org/wiki/Single-precision_floating-point_format

...