error when porting C code to Python (bitwise manipulation)

Harald Luessen harald.luessen at gmx.de
Thu Jul 10 22:04:49 CEST 2008


On Thu, 10 Jul 2008 Jordan wrote:

>On Jul 10, 1:35 pm, MRAB <goo... at mrabarnett.plus.com> wrote:
>> On Jul 10, 4:56 am, Jordan <JordanNealB... at gmail.com> wrote:
>>
>>
>>
>> > I am trying to rewrite some C source code for a poker hand evaluator
>> > in Python.  Putting aside all of the comments such as just using the C
>> > code, or using SWIG, etc.  I have been having problems with my Python
>> > code not responding the same way as the C version.
>>
>> > C verison:
>>
>> > unsigned find_fast(unsigned u)
>> > {
>> >     unsigned a, b, r;
>> >     u += 0xe91aaa35;
>> >     u ^= u >> 16;
>> >     u += u << 8;
>> >     u ^= u >> 4;
>> >     b  = (u >> 8) & 0x1ff;
>> >     a  = (u + (u << 2)) >> 19;
>> >     r  = a ^ hash_adjust[b];
>> >     return r;
>>
>> > }
>>
>> > my version (Python, hopefully ;)):
>>
>> > def find_fast(u):
>> >     u += 0xe91aaa35
>> >     u ^= u >> 16
>> >     u += u << 8
>> >     u ^= u >> 4
>> >     b  = (u >> 8) & 0x1ff
>> >     a  = (u + (u << 2)) >> 19
>> >     r  = a ^ hash_adjust[b]
>> >     return r
>>
>> > As far as I understand the unsigned instructions in C just increase
>> > amount of bytes the int can hold, and Python automatically converts to
>> > longs which have infinite size when necessary, so I am not sure why I
>> > am getting different results.
>>
>> > I assume that I am missing something fairly simple here, so help a
>> > n00b out if you can :)
>>
>> > Thanks in advance,
>>
>> > jnb
>>
>> You want to restrict the values to 32 bits. The result of + or << may
>> exceed 32 bits, so you need to mask off the excess bits afterwards.
>>
>> def find_fast(u):
>>     mask = 0xffffffff
>>     u  = (u + 0xe91aaa35) & mask
>>     u ^= u >> 16
>>     u  = (u + (u << 8)) & mask # can get away with only 1 mask here
>>     u ^= u >> 4
>>     b  = (u >> 8) & 0x1ff
>>     a  = ((u + (u << 2)) & mask) >> 19 # can get away with only 1 mask
>> here
>>     r  = a ^ hash_adjust[b]
>>     return r
>>
>> HTH
>
>Well, I guess there are two problems....the masking and the fact the
>in C it seems to for some reason overflow and become a negative
>value....still not sure why it does it....So the code with just
>masking doesn't work, you still need some sort of weird inversion like
>the ~(0xFFFFFFFF - u).....weird
>
>anyone?

In C unsigned can not be negative. Why do you believe 
the numbers are negative? If your debugger is telling 
you this thow away the debugger and use printf. 
If printf is telling you this then use the right format.
printf("%u", u); // for unsigned int u
printf("%lu", u); // for unsigned long u
printf("%x", u); 
or
printf("0x%08x", u); // to see u in hex

Harald




More information about the Python-list mailing list