0

So I was working on a simple binary to decimal script and an error occurred where there is a possible loss of precision when multiplying by a power. This is the code block in question, all it does is times the 1's and 0's in binary by 2 to the power of the strings length minus how many iterations the loop has gone through. It then add that result to z, and repeats.

public int decimal(String x){
    int z=0;
    for(int a=0;a<x.length();a++){
        z=z+Integer.parseInt(x.substring(a,a+1))*Math.pow(2,x.length()-a);
    }
    return z;
}
jocopa3
  • 796
  • 1
  • 10
  • 29

3 Answers3

4

Replace:

Math.pow(2,x.length()-a)

with:

1 << (x.length() - a)

And you'll be fine as long as integers do not overflow. You are unnecessarily using doubles, not to mention Math.pow isn't the most effective and straightforward way to compute the power of 2.

BTW is the whole point of decimal() method is to parse binary string? If so, try this:

public int decimal(String x){
  return Integer.parseInt(x, 2);
}

Yes, that's it.

Tomasz Nurkiewicz
  • 334,321
  • 69
  • 703
  • 674
  • The whole point was to translate the binary into an integer, and once again thanks for mentioning the replacement for the power. – jocopa3 Apr 24 '12 at 22:07
  • 2
    @jocopa3: if you want to convert binary like `"10010"` to int (18 in this case), I have given you the one-liner, that is much faster, safer and readable. – Tomasz Nurkiewicz Apr 24 '12 at 22:17
  • +1: Math.pow is very expensive whereas shift is on of the cheapest operations. – Peter Lawrey Apr 25 '12 at 05:35
1

I believe you are multiplying a double by an int and storing the value in an int. Some casting might fix it, try this;

public int decimal(String x){
    int z=0;
    for(int a=0;a<x.length();a++){
        z=z+(int)(Integer.parseInt(x.substring(a,a+1))*Math.pow(2,x.length()-a));
    }
    return z;
}

And bitwise commands will speed this up a whole bunch, and will remove the need for casting altogether:

public int decimal(String x){
    int z=0;
    for(int a=0;a<x.length();a++){
        z+=Integer.parseInt(x.substring(a,a+1)) << (x.length()-a);
    }
    return z;
}
lynks
  • 5,599
  • 6
  • 23
  • 42
  • Thanks, I've actually never heard of bitwise commands before, I might research them. I didn't also realize you could get a double out of using strictly integers either. – jocopa3 Apr 24 '12 at 22:04
  • Math.pow returns a double, as do most of the Math. functions. The **<<** is a 'left-shift' it slides all the bits in the int to the left (preserving 2's complement signing, but don't worry too much about that), this has the effect of doubling the value of the int (binary) in much the same way as adding a zero to a number multiplies it by 10 (decimal) – lynks Apr 24 '12 at 22:06
0

You have an off-by-one error. The function returns a value twice as big as it should be. For instance, decimal("1") == 2. Change it to Math.pow(2,x.length()-1-a).

But since the result is an integer, it's better to do everything with integral types, so use a left-shift like the others have said.

You don't even have to calculate powers of two. You can just multiply the partial result by two each time.

public int decimal(String x) {
    int z=0;
    for (int a = 0; a < x.length(); a++) {
        z = 2 * z + Integer.parseInt(x.charAt(a));
    }
    return z;
}
Derek Ledbetter
  • 4,675
  • 3
  • 20
  • 18