0

In python 2.7, the following code returns the correct result (-18027917)

from __future__ import print_function

def twos_comp(val, bits):
    if (val & (1 << (bits - 1))) != 0:
        val -= 1 << bits
     return val

valBinary = "110111011001110101001110011"
print(twos_comp(int(valBinary, 2), len(valBinary)))

In JavaScript (Node.js) the following code returns an incorrect result (1995238003)

function toTwosComplement(val, bits) {
    if ((val & (1 << (bits - 1))) != 0) {
        val -= (val - 1) << bits;
    }
    return val;
}

valBinary = "110111011001110101001110011";  // same as python example
console.log(toTwosComplement(parseInt(valBinary, 2), valBinary.length));

Evidently there is something different about the behaviour of the bit operators (or int / parseInt) but I haven't been able to see what it is.

cookie monster
  • 10,671
  • 4
  • 31
  • 45
RoyHB
  • 1,715
  • 1
  • 22
  • 38
  • Do the results change if you pass the right values for `val` and `bits` directly? That would rule out `parseInt` as cause, leaving `toTwosComplement`. –  Aug 05 '14 at 16:48

2 Answers2

6

First,

val -= (val - 1) << bits;

and

val -= 1 << bits

are not equivalent.

Since your binary string is 27 digits long, this is most likely the source of your problem.


More generally, the two languages have very different definitions of the term number.

Python has arbitrary precision integers.

Long integers have unlimited precision.

By contrast, JavaScript has IEEE 64b doubles pretending to be integers and bitwise operators that truncate their operands to 32 bits.

Number is 64-bit floating point, similar to Java's double and Double. There is no integer type. Division between two integers may produce a fractional result.

This means you can store at most 52 bits of precision, and if the highest order bit is greater than 2**52, then low order bits are truncated.


Because of the floating point nature of JavaScript, the least significant bits of a large binary number might be rounded off, and the most significant bits might be thrown out by (<<).

Community
  • 1
  • 1
Mike Samuel
  • 118,113
  • 30
  • 216
  • 245
  • Thanks Mike (and Carl). I must have messed up the guilty line at some point but, having fixed it, the javascript version now seems to work. I accepted Mike's answer because it provides significant additional info but upticked Carls because it too was correct. Both of you guys are Champions! – RoyHB Aug 06 '14 at 00:11
1

Why do these lines not match?

Python:

    val -= 1 << bits

JS:

    val -= (val - 1) << bits;
Carl
  • 905
  • 5
  • 9