我有以下代码来测试从double到long的转换:
double dVal = (double)(long.MaxValue); // 9.2233720368547758E+18;
if (dVal <= long.MaxValue && dVal >= long.MinValue)
{
long lVal1 = (long)(dVal); // gives -9223372036854775808 !!!
Console.WriteLine($"lVal1 = {lVal1}");
long lVal2 = Convert.ToInt64(dVal); // gives System.OverflowException
}
由于double类型的截断或舍入,我预计lVal1 / 2为9223372036854775807或9223372036854775800。
如何在所有情况下正确地将double转换为long?框架中是否已存在某些内容或我是否需要实现它?
答案 0 :(得分:1)
由于@HimBromBeere声明这是一个舍入错误。 long
和double
数据类型都使用64位(8字节)来表示它们的编号。但由于int
是一个整数类型,它会精确地存储整数值,它们的最小值和最大值之间没有任何内容。 double
但是是一个浮点数,它具有更大的范围(在最小/最大值方面,但也包括非整数值,包括非常小的值。这是以精确度为代价的double
例如,与long.MaxValue
无法区分long.MaxValue-1
和long
的方式相同,将无法区分0.1
和0.2
。< / p>
答案 1 :(得分:1)
为什么你期待你的期望? C#文档很清楚这两种情况会发生什么:
案例1:使用显式强制转换(来自here)
从双精度投射当你从double或float值转换为整数类型时, 值被截断。如果得到的积分值在...之外 目标值的范围,结果取决于溢出 检查上下文。在已检查的上下文中,出现OverflowException 抛出,而在未经检查的上下文中,结果是未指定的 目的地类型的值。
案例2:调用Convert.ToInt64(来自here)
例外
发生OverflowException
值大于MaxValue或小于MinValue。
您的问题的答案取决于您希望在这些情况下做什么?您必须进行显式强制转换的原因是因为有可能丢失信息(因为双精度数可以存储不适合长整数的值)。你必须告诉编译器你想在这些边缘情况下做什么。