Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

BigDecimal Class in Java - Reason behind Constant values

Tags:

java

operators

I am working out with Java Puzzlers second puzzle.

public class Change {
  public static void main(String args[]) {
    System.out.println(2.00 - 1.10);
  }
}

You will think the answer is 0.9. But it is not. If you workout this you will get 0.8999999. The solution given is

System.out.println(new BigDecimal("2.00").subtract(new BigDecimal("1.10")));

Now it will print 0.9. I understood why it prints 0.89999. But while I am curiously debugging BigDecimal class, I found there are many constant values substituted in most of the places. I'll list all those below and interested to know the reason behind it.

BigDecimal.java line number 394,

               while (len > 10 && Character.digit(c, 10) == 0) {
                    offset++;
                    c = in[offset];
                    len--;
                }

Here Character.digit(c,10).

public static int digit(char ch, int radix) {
        return digit((int)ch, radix);
    }

Here 10 is passed as radix.
Q1. Why 10 is passed there.??

BigDecimal.java line number 732

int sign = ((valBits >> 63)==0 ? 1 : -1);
        int exponent = (int) ((valBits >> 52) & 0x7ffL);
        long significand = (exponent==0 ? (valBits & ((1L<<52) - 1)) << 1
                            : (valBits & ((1L<<52) - 1)) | (1L<<52));
        exponent -= 1075;

Q2. If you look into the code in depth, you can understand what the valBits is, and I am unable to understand why rightshift is used some where?

Q3. Here also you can see there as many constants like 63, 52 are used. Why?

Q4. I can understand that the hexadecimal 0x7ffL used here will increase the speed of execution. Again why BitWise & operator is used there with the hexadecimal constant.

I hope my question is clear. Sincerely your patience is appreciated.

like image 325
Vignesh Gopalakrishnan Avatar asked Oct 19 '22 06:10

Vignesh Gopalakrishnan


1 Answers

Q1: Of course, the radix is the base of the computation. You're are using a digit in base 10 ;)

Q4: 7ff in binary: 0111 1111 1111

If you read the explanation of the bit shift operators, Java "Bit Shifting" Tutorial? you will see that >> 63 discard the 63 first bits and keep the last one. The last bit is the sign bit (for signed types). If it is 1 then the integer is negative, hence the int sign there.

Also, you can refer to https://en.wikipedia.org/wiki/Floating_point for the definition of the floating point. The 52 is to distinguish between exponent and significand.

Q4: Of course, for the exponent, you don't want to use the 'sign' bit in it, since it's not a part of the exponent, hence the mask with 7ff. The Bitwise & 0x7ff just do that; it will only put a 0 on the first bit, and leave the other to the same state. (see the truth table of the 'AND' operator https://en.wikipedia.org/wiki/Truth_table)

Edit:

Q4 complementary: If the exponent is for example 12, then the first bit will be something like:

0000 0000 1100 ... (positive value) (ex: 1x10^12)
1000 0000 1100 ... (negative value) (ex: -1x10^12)

But: 1000 0000 1100 is 2060 decimal.

if you apply the 'mask':

  1000 0000 1100 & 0111 1111 1111 -> 0000 0000 1100 (12 decimal)
  AND
  0000 0000 1100 & 0111 1111 1111 -> 0000 0000 1100 (12 decimal)

That's what the 0x7ff is for.

like image 181
JFPicard Avatar answered Oct 29 '22 23:10

JFPicard