"Steven D'Aprano" <[email protected]> wrote
They are not gone however there are still 32 bits in an integer so
the top bits *should* be set to zero.

No, Python ints are not 32 bit native ints. They're not even 64 bit ints. Python has unified the old "int" type with "long", so that ints automatically grow as needed. This is in Python 3.1:

Valid point but irrelevant to the one I was making which is that the number after shifting is longer than 8 bits.

But glitches can occur from time to time...

If Python had a glitch of the magnitude of right-shifting non-zero bits into a number, that would be not just a bug but a HUGE bug.

Bit shifting is machine specific. Some CPUs (the DEC PDP range from memory is an example) will add the carry bit for example, most will not. But you can never be sure unless you know exactly which artchiotecture the program will run on.
And of course data can always be corrupted at any time so its
always wise to take as many precautions as possibe to keep it clean (although corruption within the CPU itself is, I agree, extremely unlikely)

be as serious as having 1+1 return 374 instead of 2. Guarding against (say) 8 >> 1 returning anything other than 4

Not if you have a 4 bit processor and the previous opertation set the carry flag. In that case returning 12 would be emminently sensible....and used to be a common assembler trick for recovering from overflow errors.

guarding against 8//2 returning something other than 4: if you can't trust Python to get simple integer arithmetic right,

But ths is not simple integer arithmetic it is bit m,anippulation. You can use bit manipulation to fake arithmetic but they are fundamentally different operations and may not always produce the same results depending on how the designer built it!

trust it to do *anything*, and your guard (ANDing it with 255) can't be trusted either.

Nothing can be trusted 100% on a computer because, as you say the guard might itself be corrupted. Itas all about risk management. But when it comes to bit operations I'd always have at least one extra level of check, whether it be a mask or a checksum.

It is certainly good practice if you are dealing with numbers which might be more than 24 bits to start with:

Its more than good practice there, its essential.

But *if* you know the int is no more than 32 bits, then adding in a guard to protect against bugs in the >> operator is just wasting CPU

It may not be a bug it may be a design feature.
Now all modern CPUs behave as you would expect but if you are running on older equipment (or specialised hardware - but that's more unlikely to have Python onboard!) you can never be quite sure how bitwise operations will react at boundary cases. If you know for certainty what the runtime environment will be then you can afford to take a chance.

In the case in point the & 255 keeps the coding style consistent and provides an extra measure of protection against unexpected oddities so I would keep it in there.

cycles and needlessly complicating the code. The right way to guard against "this will never happen" scenarios is with assert:

assert n.bit_length() <= 32  # or "assert 0 <= n < 2**32"

I would accept the second condition but the mask is much faster.
bit_length doesn't seem to work on any of my Pythons (2.5,2.6 and 3.1)

This has two additional advantages:

(1) It clearly signals to the reader what your intention is ("I'm absolutely 100% sure than n will not be more than 32 bits, but since I'm a fallible human, I'd rather find out about an error in my logic as soon as possible").

The assert approach is perfectly valid, but since the mask is more consistent I'd still prefer to use it in this case.

Alan G.

_______________________________________________
Tutor maillist  -  [email protected]
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor

Reply via email to