Forums Register Login

Value changed after casting from float to double?

+Pie Number of slices to send: Send
Hi

Maybe this is a very old topic and has been discussed thousands of times before, but now it gives me a big headache.

In my current project, I need to receive data from a legacy program. What I expected is a double value, i.e. 3.14, and what is given to me is a float value, i.e. 3.14.
When the float value casts to a double value, to my surprise, the resulted value changed and some no-zero decimals are generated in the cast result!

In order to investigate this issue, I did a quick test and the result is very interesting.

Here is my sample code

float testFloat = (float) 3.14;
double testDouble = 3.14;
double testDouble2 = (float)3.14;
System.out.println("testFloat:" +testFloat);
System.out.println("testDouble:" +testDouble);
System.out.println("testDouble2:" +testDouble2);

Here is the result
testFloat:3.14
testDouble:3.14
testDouble2:3.140000104904175

Clearly after casting, float 3.14 changed to 3.140000104904175

Why float 3.14 does not stay as double 3.140000000000000 and how to solve it?

BTW, I an using Oracle JDeveloper 10g, results are the same whether it is running in hotpot JVM or oracle OJVM

Thanks

Howard
+Pie Number of slices to send: Send
Not an advanced topic.

The float and double types are floating-point. All such types have limited precision and cannot represent all numbers accurately. Because they are binary, not decimal, some numbers that look "simple" (e.g. 3.14) in decimal still cannot be represented exactly by floating-point.

So questions about the exact value of float and double variables are not very interesting at all. Inaccuracy is a feature of these types, and you either have to live with it, or choose a different type.
+Pie Number of slices to send: Send
"Howard"

Welcome to JavaRanch!

Please can you update your display name so it complies with our Naming Policy. You can do this here.

Thanks.
+Pie Number of slices to send: Send
... and as Peter Chase points out, this isn't really an advanced topic. I'll move this to a more suitable forum.
+Pie Number of slices to send: Send
Hi

Thank you very much for your prompt response!

I very agree with you on that the inaccuracy is introduced by the floating-point number binary representation.

Besides the Java test, we also did a c++ test on Windows.

double d = (float) 3.14;
printf(�%0.20lf�, d);

The result is 3.14000000000000010000.

Why Java is not as accurate as C++? Is it because of different Java compiler implementation? Or because of different JVM implementation?

Thanks again

Howard
+Pie Number of slices to send: Send
Posted by Howard Zhao

Why Java is not as accurate as C++?

It's not a case of accuracy; both figures are as accurate as each other.
It's a case of precision.

I am not sure about C++, but in C and C#, float values are expressed as 32-bit IEEE 754 (as here in the JLS) format. The float type has approx 6 or 7 significant figures' precision, unless you go into small fractions where |x| < 1/Float.MAX_VALUE (2.938736 e -39). The Java example you quote seems to give about 7 significant figures.
You are familiar with the concept of extension of floating-point numbers? The JVM can use increased bits for intermediate operations in arithmetic, unless you are using strictfp arithmetic, which sacrifices precision for reproducibility, so the calculations give exactly the same result on any computer. Here the JLS tells us about strictfp. It might be that the C++ compiler you are using can extend the limits of the number for enhanced precision.

As you say, this will vary from compiler to compiler and VM to VM, but when
I tried your casts, in C with 20 places after the decimal point, I got,
  • testFloat = 3.14000010490417480000
  • testDouble = 3.13999999999999968000, and,
  • testDouble2 = 3.13999999999999968000 Press any key to continue ...
  • and copying and pasting your Java code:
  • A:\>java FloatCast
  • testFloat:3.14
  • testDouble:3.14
  • testDouble2:3.140000104904175
  • That is as far as I can get with it, but the lesson is that floating-point arithmetic always has some imprecision to it.
    CR
    +Pie Number of slices to send: Send
    I tried the same sort of thing in C# and got:-
    testFloat = 3.14, testDouble = 3.14, testDouble2 = 3.14000010490417
    CR
    +Pie Number of slices to send: Send
    Hi
    Thank all of you very much for the replies.
    I have decided to change all the float-type variables to double-type.

    Thanks again.

    Howard
    +Pie Number of slices to send: Send
    -----------------------------------------------
    Originally posted by Howard Zhao

    float testFloat = (float) 3.14;
    double testDouble = 3.14;
    double testDouble2 = (float)3.14; //(1)
    ----------------------------------------------
    I changed the line (1) to
    double testDouble2 = (double)3.14;

    the result is :

    testFloat:3.14
    testDouble:3.14
    testDouble2:3.14

    Cheers,
    Parshuram.
    +Pie Number of slices to send: Send
    my prof said that floating point values are "bad" and that no one really

    uses them anymore... i cant really remember why he said that, but this

    example of conversion gives me an idea....

    is this opinion of "floats are bad and out" wrong?

    Justin
    +Pie Number of slices to send: Send
     

    Originally posted by Justin Fox:

    is this opinion of "floats are bad and out" wrong?



    Either you misinterpreted what s/he said, or... not, sadly. Maybe s/he was telling you that using floating-point to represent finite decimals like monetary amounts is bad -- and that much is correct.

    But in either case, no, floating point number aren't bad, not at all. What's bad is assuming that they're exact.
    It's just a flesh wound! Or a tiny ad:
    a bit of art, as a gift, the permaculture playing cards
    https://gardener-gift.com


    reply
    reply
    This thread has been viewed 4883 times.
    Similar Threads
    Float.valueOf() method and NumberFormatException
    difference between parsexxx() and valueOf()
    parseXxx() and valueOf()
    Casting from double to int leading to in correct data for very specific numbers
    Passing Obj Ref vs value and primitives
    More...

    All times above are in ranch (not your local) time.
    The current ranch time is
    Apr 15, 2024 23:46:04.