给出以下代码:
long l = 1234567890123;
double d = (double) l;
以下表达式是否保证为真?
l == (long) d
我应该不这么认为,因为随着数字变大,两个双精度数之间的差距会超过1,因此转换回产生不同的长值。如果转换没有采用大于long值的值,那么这可能也会更早发生。
对此有明确的答案吗?
答案 0 :(得分:5)
long
有很多double
个值无法完全表示。事实上,具有是这种情况,因为两种类型都以64位表示,并且显然有很多double
值在long
中无法表示(例如0.5)
简单示例(Java然后是C#):
// Java
class Test {
public static void main(String[] args) {
long x = Long.MAX_VALUE - 1;
double d = x;
long y = (long) d;
System.out.println(x == y);
}
}
// C#
using System;
class Test
{
static void Main()
{
long x = long.MaxValue;
double d = x;
long y = (long) d;
Console.WriteLine(x == y);
}
}
我在做这件事时发现了一些非常奇怪的虽然...在C#中,long.MaxValue
“工作”就打印错误而言......而在Java中,我不得不使用{ {1}}。我的猜测是,这是由于某些情况下的一些内联和80位浮点运算...但它仍然很奇怪:)
答案 1 :(得分:1)
你可以测试它,因为有很多长值。
for (long l = Long.MIN_VALUE; l<Long.MAX_VALUE; l++)
{
double d = (double) l;
if (l == (long)d)
{
System.out.println("long " + l + " fails test");
}
}
不需要多次迭代来证明;
l = -9223372036854775805
d = -9.223372036854776E18
(长)d = -9223372036854775808
答案 2 :(得分:1)
我的代码以0开头并增加100,000,000。未通过测试的最小数字为2,305,843,009,300,000,000(19位)。因此,任何低于2,305,843,009,200,000,000的正长度都可以完全由双打表示。特别是,18位数的长度也可以用双精度来表示。
顺便说一下,我对这个问题感兴趣的原因是我想知道我是否可以使用双精度来表示时间戳(以毫秒为单位)。由于当前时间戳大约为13位数(并且它们需要很长时间才能达到18位数),我会这样做。