我注意到当要转换的数字很大但仍然远低于long
的最大值时,从double
到long
的转换会改变值。
例如,有人能解释一下为什么这个转换并没有按预期工作吗:
Convert.ToInt64(600000000000040000d)
// Return => 600000000000039936
Convert.ToInt64(600000000000040000L)
// Return => 600000000000040000
这会导致我的公式出现问题...谢谢。
我注意到当要转换的数字很大但仍然远低于long
的最大值时,从double
到long
的转换会改变值。
例如,有人能解释一下为什么这个转换并没有按预期工作吗:
Convert.ToInt64(600000000000040000d)
// Return => 600000000000039936
Convert.ToInt64(600000000000040000L)
// Return => 600000000000040000
这会导致我的公式出现问题...谢谢。
好的,double
只有 52 位 尾数(详见https://zh.wikipedia.org/wiki/IEEE_浮点数算术);这就是为什么 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
维基百科:https://en.wikipedia.org/wiki/Single-precision_floating-point_format(单精度浮点数格式)
// Double to long
double av = 600000000000040000L;
long lg = (long)av;
long g1 = Convert.ToInt64(av);
// long to Double
double dbl = (double)g1;
double d = Convert.ToDouble(g1);