2

I have a javascript program there use bitwise OR operator to get a OR result from two numbers:

Sample code:

<!DOCTYPE html>
<html>
<body>

<p>Click the button to return the number of characters in the string "Hello World!".</p>

<button onclick="myFunction()">Try it</button>

<p id="demo"></p>

<script>
function myFunction() {
    var str = "80400001";
    var a = parseInt(str, 16);
    var str = "12345678";
    var b = parseInt(str, 16);
    n = b|a;
    document.getElementById("demo").innerHTML = n;
}
</script>

</body>
</html>

But the result is always negative, that is not my expected value. Result:

-1837869447

Eventhough I try to OR a number with zero, the result is still negative...

It doesn't happen in Java, but in Javascript.

Can you tell how can I get the same result as that in Java?

Jared Smith
  • 19,721
  • 5
  • 45
  • 83
lei lei
  • 1,753
  • 4
  • 19
  • 44
  • 1
    You're parsing the strings as hex? Also I edited your question, that's the bitwise OR operator, logical OR is `||`. – Jared Smith Sep 13 '18 at 02:07
  • 1
    This `|` is not a logical OR it is a bitwise operator. This `||` is a logical OR. – gforce301 Sep 13 '18 at 02:09
  • @gforce301 Is any `pipe` exists in Javascript? – Frank AK Sep 13 '18 at 02:12
  • @FrankAK it's bitwise OR. JavaScript has a pretty full range of bitwise operators, not that anyone ever uses them. – Jared Smith Sep 13 '18 at 02:13
  • @JaredSmith Thanks! yes, I mean bitwise OR. Yes, I want to parsing the strings as hex. – lei lei Sep 13 '18 at 02:19
  • I really can't figure out what's going on here, I fired up a clojure repl (i.e. java) and `(bit-or 0x80400001 0x12345678)` returns 2457097849. Same for python3. – Jared Smith Sep 13 '18 at 02:19
  • it most likely have to do with javascript doesnt have unsigned int, but i dont know why the number is positive when var a is positive and switch to negative when applied a bitwise operator. but here is one way around it parseInt((((a|b) >>> 1).toString(2) + "1"), 2), use unsigned shift to remove the signed bit, then add back the bit pushed off, and use parseInt to parse it back. You need to remember the bit pushed off tho, probably can do that by using %2. – Chris Li Sep 13 '18 at 02:32
  • @ChrisLi actually its that JS doesn't have 64 bit ints and her first number is too big. See my answer. – Jared Smith Sep 13 '18 at 02:33
  • yea that is what i meant – Chris Li Sep 13 '18 at 02:34

3 Answers3

4

You can use this change signed int to unsigned int:

n>>>0

var str = "80400001";
var a = parseInt(str, 16);
var str = "12345678";
var b = parseInt(str, 16);
n = b | a;
    
console.log((n>>>0).toString(16))

see: Bitwise operations on 32-bit unsigned ints?

Jared Smith
  • 19,721
  • 5
  • 45
  • 83
cyrilluce
  • 977
  • 9
  • 11
3

I believe the problem is that unlike e.g. Java and Python JavaScript does not have a 64 bit integer type. When you use the bitwise operators in JS, the number is truncated to 32 bits, the operation is performed, then it is cast back to an IEEE 754 float. 0x80400001 is 2,151,677,953 which is bigger than 2,147,483,647 (max signed 32 bit int) and you're losing the significant bits which is giving the odd result.

There are arbitrary size integer libraries one can use.

Also checkout cyrilluce's answer for a way to do it without an external lib.

Jared Smith
  • 19,721
  • 5
  • 45
  • 83
2

The reason is because number in javascript is 64bit floating point, but bitwise operator work on 32bit int, in your example variable a is larger than 31^2, so when you apply a bitwise operator it changed to negative. One way I can think of around it is to use unsigned right shift to push off the signed bit, and add back the bit pushed off.

var str = "80400001";
var a = parseInt(str, 16);
var str = "12345678";
var b = parseInt(str, 16);
n = parseInt(((a|b) >>> 1).toString(2) + (a%2|b%2), 2);
console.log(n)
Chris Li
  • 2,628
  • 1
  • 8
  • 23