I am trying to solve the problem 2’s complement here (sorry, it requires login, but anyone can login with FB/google account). The problem in short is to count the number of ones appearing in the 2’s complement representation of all numbers in a given range [A, B] where A and B are within the 32-bit limits (231 in absolute value). I know my algorithm is correct (it’s logarithmic in the bigger absolute value, since I already solved the problem in another language).
I am testing the code below on my machine and it’s giving perfectly correct results. When it runs on the Amazon server, it gives a few wrong answers (obviously overflows) and also some stack overflows. This is not a bug in the logic here, because I test the same code on my machine on the same test inputs and get different results. For example, for the range [-1548535525, 662630637] I get 35782216444 on my machine, while according to the tests, my result is some negative overflow value.
The only problem I can think of, is that perhaps I am not using Int64 correctly, or I have a wrong assumption about it’s operation.
Any help is appreciated. Code is here.
The stack overflows are a bug in the logic.
Whenever you call
countOnes'with a negative argument, you get a nonterminating computation, since theshiftRis an arithmetic shift and not a logical one, so you always shift in a 1-bit and never reach 0.But even with a logical shift, for negative arguments, you’d get a result 32 too large, since the top 32 bits are all 1.
Solution: mask out the uninteresting bits before calling
countOnes',There are some superfluous guards in
countOnes,The integer overflows on the server are caused by
because the server has a 32-bit GHC, while you have a 64-bit one. The shift distance/bit width
mis anInt(and because it’s used as the shift distance, it has to be).Therefore
is an
Inttoo. Form >= 28, that overflows a 32-bitInt.Solution: remove a
$Then the
1that is shifted is anInteger, hence no overflow.