4

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.

Girish
  • 93
  • 8

3 Answers3

4

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.

Jason C
  • 38,729
  • 14
  • 126
  • 182
  • Yes, double timeElapsed = (now - then) / 1000.0; is good enough here! – Girish Aug 05 '14 at 08:31
  • @jason - see edits to my post. Considering that my answer exactly agrees with your conclusion I think you are being overly strict in calling it "wrong" and "not true". – user949300 Aug 08 '14 at 16:14
-1

I'd go

double timeElapsed = (now - then) / 1000.0;

But, unless you ar doing this 1000s of times in a tight loop it doesn't matter. Do whatever seems clearest to you.

Some claim that "there is no Double.valueOf(long)". Well, Java behaves as if there were. Double.valueOf(2L) does exactly what one thinks it should do. In your code, unless the test were running for years, Double.vaueOf(now - then) would do exactly what you thought it would do. I'd argue that Double.valueOf(long) does exist. It's just not in the Javadocs. If I write double d = 3 + 4.5 does that not exist?

I agree with others here that the Double.valueOf(now - then).doubleValue() is silly, but it should be avoided because it adds confusion, not because it "serves no purpose". With the advent of autoboxing and unboxing, many methods serve no purpose, except, possibly to make things clear. If you think that the explicit Double makes things clearer (in this example, I think not, but your mileage may vary) you should write the code that way.

For example, I still often use the "unnecessary" double primitive = someDouble.doubleValue() to remind myself and other programmers that otherwise auto-unboxing would be happening and a mysterious NPE may be thrown.

Jason C
  • 38,729
  • 14
  • 126
  • 182
user949300
  • 15,364
  • 7
  • 35
  • 66
  • @Girish This answer is wrong and neglects to mention the actual problem, which is that there is no `Double.valueOf(long)`, and that an implicit cast to a `double` is being used in the first example so that `Double.valueOf(double)` can be called, thus making it useless regardless. – Jason C Aug 05 '14 at 07:37
  • @JasonC - This answer solves the problem. There is no cast or valueOf required. – Girish Aug 05 '14 at 08:28
  • @Girish This answer doesn't explain why, doesn't explain what is actually happening in yor example, and claims that "whatever seems clearest [of your two options]" is best, which is not true. It skips the important parts. Your question "Is this the right approach?" is not answered here. And a cast *is* happening, by the way, even if it is not explicit - it is important to always be aware of that. – Jason C Aug 05 '14 at 08:40
  • @JasonC - Ok. I understand what you are getting at! It is done! – Girish Aug 05 '14 at 08:44
  • [There is no `Double.valueOf(long)`](http://docs.oracle.com/javase/7/docs/api/java/lang/Double.html) and Java does not behave "as if their were". `long` to `double` is a [widening conversion](http://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.2), which are allowed automatically. **KEY:** Note that `Double.valueOf(11398895185373143L)`, for example, [will not yield the result that you think](http://ideone.com/zCmQzg) - the assertion that "Java behaves as if ..." here is demonstrably incorrect and is also a misinterpretation of what an automatic widening conversion is. – Jason C Aug 08 '14 at 16:35
  • I also disagree with your assertion that an NPE thrown from auto-unboxing is "mysterious" - the location is quite clear in a stack trace; however while I *personally* believe this is not a compelling reason to avoid auto-unboxing, I do agree with you in that being clear is reasonable, and the choice there is a valid style choice. – Jason C Aug 08 '14 at 16:55
  • Jason - please read in more detail. 11398895185373143L milliseconds corresponds to 36145 years. OP was timing his program, it is not possible that his program has been running for 36000 years. Which I explicitly noted: "unless the test were running for years". Also, the "result that I think" is that the double will NOT exactly match the integer for extremely large numbers. As for the NPE being "mysterious", it made it to one of the Java Puzzlers books. – user949300 Aug 08 '14 at 23:41
-1

I've written the following 2 methods:

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;
}

As you can see this is the simplified version of yours code; I did it to make the experiment cleaner.

Now, I compiled the code and then printed the bytecode using 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

As we can see the code of 2 methods is similar, but in second case we have (as expected) invocations of valueOf() and then of doubleValue().

So, it seems that unless you have some very special reasons you just should use casting. It is shorter, clearer and more cheaper in terms of CPU usage.

AlexR
  • 114,158
  • 16
  • 130
  • 208
  • You didn't need to go through all this. A quick glance at the documentation for [`Double`](http://docs.oracle.com/javase/7/docs/api/java/lang/Double.html) shows that `.valueOf(long)` doesn't even exist. The case is implicit and `.valueOf(double)` is called. So regardless of how it compiles, `.valueOf` here is either equivalent to or worse than an explicit cast. – Jason C Aug 05 '14 at 07:38
  • (You can even see this in the `l2d` instruction that you skipped over in your analysis.) – Jason C Aug 05 '14 at 07:45
  • @JasonC, you are right, it is pretty obvious. I just wanted some "scientific" evidence. – AlexR Aug 05 '14 at 07:53
  • Sometimes writing such example is faster and (IMHO) more interesting than reading documents. However, you are right: I like RTFM too. – AlexR Aug 05 '14 at 07:55
  • For the sake of honesty; I did downvote this answer, not because of the `valueOf(long)` thing or documentation, but solely because you missed the `l2d` in your explanation, which is key to the analysis of your experiment results. – Jason C Aug 05 '14 at 07:57
  • `l2d` instruction presents in both versions, so I really do not understand what the problem is. – AlexR Aug 05 '14 at 08:05
  • Of course it does. In the first version it represents the explicit `(double)`. In the second version it represents the *implicit* cast before passing the parameter to `valueOf()`. It is a major hint that the *real* reason for using the first is not just that it is "shorter, clearer, cheaper". It is the key to the answering the OP's question of "is this the right approach?". – Jason C Aug 05 '14 at 08:08