6

I have been trying the following code in Java :

import java.math.*;

public class trial {

public static void main(String[] args) {

    // create a BigDecimal object
    BigDecimal bg;

    // create a Float object
    Float f;
    float f2 = 35912062;
    bg = new BigDecimal(35912062);

    // assign the converted value of bg to f
    f = bg.floatValue();

    String str = "Float value of " + bg + " is " + f;

    bg = new BigDecimal(f);
    String str2 = "BigDecimal value of " + bg;


    // print f value
    System.out.println( str );
    System.out.println( str2 );
    System.out.println( 35912062f );
    System.out.println(f2);
}
}

So, the following is the output I am getting :

    Float value of 35912062 is 3.5912064E7
    BigDecimal value of 35912064
    3.5912064E7
    3.5912064E7

Now, I believe that it is because this is extending the range of float but when I read this : What is the inclusive range of float and double in Java?

it shows the inclusive range of float to be : 3.40282346638528860e+38

This has made me really confused. Any links giving explanations will help.

EDIT: Say I take 25912062 inplace of 35912062, The output for 25912062 is 25912062, but for, 35912062 the output is 35912064 why is this so ?

Kartavya Ramnani
  • 800
  • 9
  • 17
  • 5
    You are conflating precision with range. Unclear what you're asking. – user207421 Aug 29 '17 at 09:50
  • @EJP My Bad, I meant Range. I will edit the question. Thanks for improving the question. But, the input for float was : 35912062 I am unsure why the output is coming to be : 3.5912064E7 – Kartavya Ramnani Aug 29 '17 at 09:52
  • 3
    What makes you think it shouldn't be? Are you aware how many decimal digits the precision of `float` amounts to? And, again, you are conflating precision with range. – user207421 Aug 29 '17 at 09:52
  • 1
    Because float only has *precision* of around 7-8 digits even though its *range* can go much higher. – Sami Kuhmonen Aug 29 '17 at 09:53
  • But isnt the range of float is : 3.40282346638528860e+38 Are you telling me, float cannot store an 8digit number correctly ? – Kartavya Ramnani Aug 29 '17 at 09:54
  • @SamiKuhmonen Will appreciate if you can please tell me how to correct this and not lose information. :( – Kartavya Ramnani Aug 29 '17 at 09:55
  • For the third or fourth time, you are confliating precision with range. If you don't understand the difference, please say so. If you want more precision, *or* more range, why are you using `float` at all, instead of `double`? – user207421 Aug 29 '17 at 09:55
  • 1
    By not using floats. If you need more *precision* then you use a datatype that has enough *precision* for your needs, as well as range. – Sami Kuhmonen Aug 29 '17 at 09:55
  • Understood. Float lacks the precision, hence even though it is able to hold an 8 digit number (because of its range), it is incorrectly showing it because of its precision of 7 or 8 digits. Hence, float will not be the correct data type to use when you need precision. – Kartavya Ramnani Aug 29 '17 at 09:59
  • 2
    @Kartavya Wrong again. It is able to store a 7-8 digit number because of its *precision*, and it is able to store an inclusive range of `1.401298464324817E-45f` to `3.4028234663852886E38f` because of its *range.* Note that this range is not what you claimed in your question. – user207421 Aug 29 '17 at 10:01
  • But @EJP : Say I take 25912062 inplace of 35912062, The output is 25912062, but for, 35912062 the output is 35912064 why is this so ? – Kartavya Ramnani Aug 29 '17 at 10:01
  • 2
    **Because of the precision.** There are 23 bits of mantissa. This allows a maximum number of integral significant decimal digits of `log10(2^23-1)`, or 6.9something. Or whatever it is. Close enough for jazz :-| Please note that your question is *entirely* about precision, and has *nothing to do* with range whatsoever. – user207421 Aug 29 '17 at 10:05
  • Thanks @EJP Understood. :) :) – Kartavya Ramnani Aug 29 '17 at 10:27
  • 1
    good article about it https://randomascii.wordpress.com/2012/03/08/float-precisionfrom-zero-to-100-digits-2/ – Mike Adamenko Aug 29 '17 at 10:33

1 Answers1

3

Basically, floating point values are stored as a pair of mantissa and exponent. The mantissa describes the significant digits of the number (think of it as a number between 0 and 9.99). The exponent is the scale. Your number is presented as mantissa * 2^x.

We are talking about a representation in the binary system, which makes even straight numbers (in the decimal system) like 35912062 to something which may not exactly fit within the precision of the mantissa. In these cases, you get some rounding issues, especially as float has a rather limited range for the mantissa.

Executing your code with double (instead of float) gives you 3.5912062E7 as result.

If your really wanna know what java (or the floating point arithmetic) makes of your number, you should do System.out.println(new Bigdecimal(123.456)) and be surprised.

The message here is, if you really need precise arithmetics always take BigDecimal. Because there are further caveats. For example, adding a large double and a small double may result in the small double to be rounded away completely. That takes us to a funny thing:

    for (float f = 35912062f; f < 55912062f; f++) {
        System.out.println(f);
    }

will never terminate. Just try it.

Jonathan
  • 2,698
  • 24
  • 37