I need to convert a long variable to double. The value of the long variable is a not a literal, it is a value returned by another method, say, System.currentTimeMillis(). I need to convert it into double for decimal calculations like converting milliseconds to seconds, without losing the decimal part.
So one way to do that is to use Double.valueOf() and then divide the .doubleValue() output by 1000.
long then = System.currentTimeMillis();
long now = System.currentTimeMillis();
double timeElapsed = Double.valueOf(now - then).doubleValue() / 1000;
Is this the right approach? Or should I simply cast them as follows?
double timeElapsed = ((double) now - (double) then) / 1000;
I am wondering which is the best way to do this.
Please shatre your opinions/suggestions.
Thanks.
There is no Double.valueOf(long)
.
What's actually happening in your first example is that now - then
is being computed, the result is long
, then it is implicitly being cast to a double
and passed to Double.valueOf(double)
. Basically, it is this:
double timeElapsed = Double.valueOf((double)(now - then)).doubleValue() / 1000;
As you can see, that serves no purpose! Note also that auto-unboxing will automatically convert a Double
to a double
, and so the doubleValue()
also serves no purpose.
The cast is the correct approach:
double timeElapsed = (double)(now - then) / 1000.0;
Which, as long as you use 1000.0
instead of 1000
, is equivalent to:
double timeElapsed = (now - then) / 1000.0;
The purpose of Double.valueOf(double)
, by the way, is just to give you a way to explicitly box a double
and convert it to a Double
if you need to. The purpose of doubleValue()
is the opposite. Neither are appropriate for your scenario. (This applies in general to all of the valueOf
/ *Value
methods on primitive wrapper classes.)
By the way, to reduce risk of precision loss (not a big risk in your case but in general), it is generally better to do the above than:
double timeElapsed = ((double)now - (double)than) / 1000.0;
Some explanation of what is happening in your example can be found here. Widening primitive conversions are allowed to happen automatically, and the JLS classifies long
to double
as a widening conversion.
However, there are risks in the long
to double
case, the primary risk being that not all values of a long
can be represented by a double
, and information can be silently lost in the conversion. Consider the following simple test (run it at 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;
}
}
This test will fail at certain values (e.g. Double.valueOf(11398895185373143L)
is not what you expect), becoming guaranteed as as the base-2 mantissa of the long
exceeds the range of the mantissa of a double
. Another simple test:
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
Output:
123456789123456789
123456789123456784.000000
123456789123456784.000000
Note the final digit.
This danger exists any time you convert an integer to a double, including in my examples above - however, it is worth noting because passing a long
to a Double.valueOf()
, in my opinion, can catch one off guard more than the others.