Test against odd numbers
Asked Answered
E

2

8

Most commanly the modulo operator % is used to test against an even or odd Number.

Now my question is, is there any Problem testing against an odd number using a bitwise AND, as it feels much more natural testing whether the rightmost bit is 1 or 0 than doing a modulo check against 2

And as the 32 bit conversion does not change the rightmost bit.

Both

(1 + Math.pow(2,52)) & 1 //1

and

(1 + Math.pow(2,52)) % 2 //1

yield the same result.

Is there a reason to prefer the modulo operator over the bitwise?

Edit: This question only accounts for values that fall in the range of 64bit precision as only even numbers can be represented precise above 2^53 and therefore both operands fail (9007199254740993 % 2 //0)

Eastereasterday answered 12/4, 2013 at 13:37 Comment(2)
Modulo is used to find the remainder of division. Coincidentally, it can be used as a parity-check.Quiddity
Just don't do that in production code. Except if it's a performance improvement after finding out through profiling that this is the bottleneck. With a comment.Oneupmanship
A
7

In JavaScript, using any bitwise operator causes the number to be first truncated to a 32-bit integer. That means it won't work for some larger values. (Well, quite a few larger values :-)

The % operator doesn't do that.

edit — hey all you nice people who've upvoted me: hold your horses :-) C5H8NNaO4 points out that the integer truncation process should preserve the low bit, which makes intuitive sense if you think about just lopping off the top part of the mantissa, and indeed some cursory "tests" indicate that it seems to work fine.

Things get more complicated of course for really large values, which when represented in imprecise floating point may be either odd or even, since the least-significant digits are missing. In other words, when the binary exponent in a floating point value results in an effective value that's larger than the mantissa capacity (53 bits I think), then you either have to consider all such numbers even (because the low bits are always zero) or else you have to consider the question indeterminate.

It should be clear that I'm not a mathematician.

Adipose answered 12/4, 2013 at 13:38 Comment(15)
+1 In addition in regards to bitwise operators. To borrow from Crockford's good parts: JavaScript doesn’t have integers. It only has double precision floating-point numbers. So, the bitwise operators convert their number operands into integers, do their business, and then convert them back. In most languages, these operators are very close to the hardware and very fast. In JavaScript, they are very far from the hardware and very slow. JavaScript is rarely used for doing bit manipulation.Pulvinate
Excellent answer. And for any who worry that % might be defined in integer terms, it's not: ecma-international.org/ecma-262/5.1/#sec-11.5.3Kattiekatuscha
For parity-checking, the conversion to 32-bit doesn't seem to matter, as the OP said. So apparently it will work, even for large integer values.Brawl
The trtuncation shouldn't change the rightmost bit as so the information about whether its even or odd doesn't get lost. for(var i=0;64>i;i++){var n=1+Math.pow(2,i);n%2!==(n&1)&&console.log(i)}console.log("Finished"); Quick test, both operators yield the same result for any power of 2 by {1..64} + 1.Eastereasterday
@FrançoisWahl: Crockford's claim that JavaScript bit-fiddling operators are "far from the hardware" is markedly out of date.Kattiekatuscha
@C5H8NNaO4 Hmm that's a good point ... I don't trust my number theory intuition (which is almost non-existant) so I'll have to try it, but that does seem like it'd be true.Adipose
@T.J.Crowder: Interesting and I even bought the latest revision of the good parts :(. Also when looking at this jsPerf test why is bit faster than mod? I would have thought with all the conversion and to and frow between ints and floats and JavaScript being appearently so far from the hardware that mod would have been faster.Pulvinate
@FrançoisWahl See T.J.'s comment.Unsociable
@MaxArt: I would have assumed that the info in the book was based on facts not just assumption. Seems I did learn something new today. I hope the book "High Performance JavaScript" I started reading recently is not going to get me into the same troubles.Pulvinate
@Adipose The conversion algorithm does posInt modulo 2^32 (read ^ as power, not XOR). So that will be even if posInt is even.Brawl
@FrançoisWahl: "I would have assumed that the info in the book was based on facts not just assumption." Crockford is a smart and well-informed person who is well worth reading, but unfortunately he does sometimes state his opinion as though it were fact, to the detriment of the book (notably around inheritance stuff). But in this case, I think it's just out of date. It was originally published before the great strides in JavaScript engines, so there's bound to be the occasional out-of-date statement in it that hasn't been caught in the new revision.Kattiekatuscha
Questions that seem simple on just one cup of coffee sometimes aren't so simple.Adipose
@Pointy: I still think my upvote is well-placed. Even more so since your edit. :-)Kattiekatuscha
@T.J.Crowder: I see. +1 for taking your time in explaining that. I'm going to see if I can find some info which is more up-to-date to ensure I know better what I'm talking about. Other than the Ecma-262 which is not the easiest read to digest.Pulvinate
@FrançoisWahl: LOL! You have the gift of understatement (about the standard, I mean).Kattiekatuscha
F
0

If your numbers will always convert nicely to a 32 bit int, then it looks like Bitwise can be faster -- I'm guessing some javascript engines can JIT it to hardware bitwise operations. I've constructed a jsperf to test it:

http://jsperf.com/evenness

I get very variable results on Firefox 20, sometimes the Bitwise is slightly faster, sometimes many times faster.

If your numbers may or may not convert nicely to 32 bit ints, then stick to modulo.

Faunie answered 12/4, 2013 at 14:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.