我需要将long变量转换为double。 long变量的值不是文字,它是另一个方法返回的值,比如System.currentTimeMillis()。我需要将其转换为double进行十进制计算,例如将毫秒转换为秒,而不会丢失小数部分。
所以一种方法是使用Double.valueOf()然后将.doubleValue()输出除以1000.
long then = System.currentTimeMillis();
long now = System.currentTimeMillis();
double timeElapsed = Double.valueOf(now - then).doubleValue() / 1000;
这是正确的做法吗?或者我应该简单地按如下方式投射它们?
double timeElapsed = ((double) now - (double) then) / 1000;
我想知道哪种方法最好。
请破坏您的意见/建议。
感谢。
答案 0 :(得分:4)
There is no Double.valueOf(long)
您的第一个示例中实际发生的是now - then
正在计算中,结果为long
,然后将其隐式地强制转换为double
并传递给Double.valueOf(double)
}。基本上就是这样:
double timeElapsed = Double.valueOf((double)(now - then)).doubleValue() / 1000;
如你所见,这没有任何意义!另请注意,自动取消装箱会自动将Double
转换为double
,因此doubleValue()
也无意义。
演员是正确的方法:
double timeElapsed = (double)(now - then) / 1000.0;
只要您使用1000.0
代替1000
,就相当于:
double timeElapsed = (now - then) / 1000.0;
顺便提一句,Double.valueOf(double)
的目的只是为了让您明确选择double
并根据需要将其转换为Double
。 doubleValue()
的目的恰恰相反。两者都不适合您的场景。 (这通常适用于原始包装类的所有valueOf
/ *Value
方法。)
顺便说一句,为了降低精确损失的风险(在您的情况下通常不是很大的风险),通常情况下执行以上操作会比以下更好:
double timeElapsed = ((double)now - (double)than) / 1000.0;
可以找到对您的示例中发生的事情的一些解释here。允许自动扩展原始转换,并且JLS将long
分类为double
作为扩展转换。
但是,long
到double
案例存在风险,主要风险是并非long
的所有值都可以由double
表示,并且信息可以在转换中无声地丢失。考虑以下简单测试(在http://ideone.com/zCmQzg运行):
for (long a = 1; ; a *= 7) {
long x = Double.valueOf(a).longValue();
if (x != a) {
System.out.println("Conversion fails at input=" + a + " output=" + x);
break;
}
}
此测试在某些值时会失败(例如Double.valueOf(11398895185373143L)
不符合您的预期),因为long
的基数2尾数超出{{1}的尾数范围,因此得到保证。 1}}。另一个简单的测试:
double
输出:
long x = 123456789123456789L;
System.out.println(x);
System.out.println(String.format("%20f", Double.valueOf(x))); // implicit
System.out.println(String.format("%20f", (double)x)); // explicit, same thing
注意最后的数字。
这种危险存在任何时间将整数转换为double,包括在上面的示例中 - 但是,值得注意的是因为将123456789123456789
123456789123456784.000000
123456789123456784.000000
传递给long
在我看来,可以比其他人更能抓住一个失控的人。
答案 1 :(得分:-1)
我要去
double timeElapsed = (now - then) / 1000.0;
但是,除非你在紧密的循环中做了这么多次,否则没关系。做任何看起来最清楚的事情。
有人声称“没有Double.valueOf(长)”。好吧,Java的行为好像有。 Double.valueOf(2L)
完全符合人们的想法。在您的代码中,除非测试运行多年,否则Double.vaueOf(now - then)
将完全按照您的想法执行。我认为Double.valueOf(long)确实存在。它只是不在Javadocs中。如果我写double d = 3 + 4.5
那不存在吗?
我在这里同意其他人认为Double.valueOf(现在 - 然后).doubleValue()是愚蠢的,但应该避免它,因为它增加了混乱,而不是因为它“没有用处”。随着自动装箱和拆箱的出现,许多方法没有用处,除非可能要清楚。如果你认为明确的Double让事情变得更清楚(在这个例子中,我认为不是,但你的里程可能会有所不同),你应该以这种方式编写代码。
例如,我仍然经常使用“不必要的”double primitive = someDouble.doubleValue()
来提醒自己和其他程序员,否则会发生自动拆箱,并且可能会抛出神秘的NPE 。
答案 2 :(得分:-1)
我已经写了以下两种方法:
public static void cast() {
long l = 123L;
double d = (double)l / 1000;
}
public static void valueOf() {
long l = 123L;
double d = Double.valueOf(l) / 1000;
}
正如您所看到的,这是您的代码的简化版本;我这样做是为了让实验更清洁。
现在,我编译了代码,然后使用javap -v
打印字节码:
public static void cast();
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=4, locals=4, args_size=0
0: ldc2_w #2 // long 123l
3: lstore_0
4: lload_0
5: l2d
6: ldc2_w #4 // double 1000.0d
9: ddiv
10: dstore_2
11: return
LineNumberTable:
line 3: 0
line 4: 4
line 5: 11
public static void valueOf();
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=4, locals=4, args_size=0
0: ldc2_w #2 // long 123l
3: lstore_0
4: lload_0
5: l2d
6: invokestatic #6 // Method java/lang/Double.valueOf:(D)Ljava/lang/Double;
9: invokevirtual #7 // Method java/lang/Double.doubleValue:()D
12: ldc2_w #4 // double 1000.0d
15: ddiv
16: dstore_2
17: return
LineNumberTable:
line 8: 0
line 9: 4
line 10: 17
正如我们所看到的,2种方法的代码相似,但在第二种情况下,我们({预期)调用valueOf()
然后调用doubleValue()
。
所以,似乎除非你有一些非常特殊的原因,你应该使用铸造。它在CPU使用方面更短,更清晰,更便宜。