Does Python need a '>>>' operator?
Bengt Richter
bokr at oz.net
Tue Apr 16 08:06:12 EDT 2002
On Mon, 15 Apr 2002 19:40:49 -0700, "Ken Peek" <Ken.Peek at SpiritSongDesigns.comNOSPAM> wrote:
[...]
>
>What I want, is an object that "looks and feels" like a 'binary twos-complement
>integer', that can be extended a byte at a time. I don't _CARE_ how the machine
>represents it internaly. It might even be in BCD for some weird CPU (for all we
>know)-- but the interface that _I_ see, is a 'binary twos-complement integer'
>made up of a finite number of bytes. I don't want to know HOW the machine
>STORES it-- I just want a consistent interface to it.
>
No prob.
>When I print it out (in decimal)-- I want it to appear the way it does now--
>sign and magnitude.
>
>When I print it out in hexadeciaml, I want the bit representation of a 'binary
>twos-complement' number, of a size (in bytes) that will represent the number
>without truncation (regardless of HOW the number is stored inside the machine.)
No prob either.
>
>| >An int type simply shifts a zero into bit 31, so that
>| >this works the same as it will on a long.
>
>Let me clarify the above-- the '>>' should behave in a manner such that the sign
>bit is COPIED to the high bit during a right shift. So-- if the number starts
>out as a positive number, it STAYS a positive number after the shift. The
No prob.
>proposed '>>>' operator forces a zero into the high bit, having no effect on the
>sign bit of a positive number, but forcing a negative (twos-complement) number
>to now be positive after the shift. Again-- I don't care HOW the number is
>represented internally-- this is the way it should always appear to the
>programmer...
Ok, but which sign bits should I keep when I shift in zeroes? I have to normalize
to something. A single sign bit is one way, not keeping to the left. Whatever sign
bits are required to fill out k*4 or k*8 bits is another. Or you can specify a
fixed width w and have it work like the 32 of in works now. But one way or another,
you have to provide a rule that results in a width to use for a particular negative
number, when you want to shift in zeroes. What's it going to be?
[...]
>|
>| In any case, you can define a function to whatever you actually want.
>| (I suspect you'll wind up specifying width explicitly). But if
>| you want a >>> operation, what width should it use? Remember, different
>| platforms may use different internal long representations.
>
>You CANNOT do this in a portable way from OUTSIDE of the object. Only the
Sure you can. See below.
>OBJECT "knows" how many bytes in an equivalent twos-complement binary number are
>required to represent the number contained in the object. Even if the internal
No, the required number of bits can be determined exactly from the numeric value.
>representation is in BCD, or a funny "17-bit per word" [an old IBM machine did
>this] format, the programmer should always "see" an array of BYTES that
>represent a twos-complement binary integer. If the long class overloads the
>'>>>' operator, and it "knows" how many "pseudo-bytes" are needed to represent
>the number, then it can damn well "do the good thing" when this method is called
>(as an operator on the long.) YOU however, are not supposed to be peeking
>inside the object (OOP rule #1-- encapsulation)-- let the object figure out how
>to do the '>>>' (and the '>>' and '<<' for that matter.)
Fine, but you have to define the meaning of >>> without "peeking inside".
Below I padded to full bytes before >>> shifting. Is that what you wanted?
(I'm not proposing this, I'm just trying to interpret your >>> so you can
see whether it makes more sense to you than it does to me ;-)
See if this does n >>> rsh the way you want:
>>> def kshr(n, rsh):
... nbytes = (len('%x' % ((n<<1)^n,))+1)/2
... return (n&((1L<<(nbytes*8))-1)) >> rsh
...
>>> hex(kshr( 0x80000000,1))
'0x40000000L'
>>> hex(kshr(-0x80000000,1))
'0x40000000L'
>>> hex(kshr( 0xf0000000,1))
'0x78000000L'
>>> hex(kshr(-0xf0000000,1))
'0x7F88000000L'
note the extra byte needed before the shift:
>>> hex(kshr(-0xf0000000,0))
'0xFF10000000L'
If I did it as intended, it figures how many bytes are necessary to hold
the sign and significant bits of n, masks n to that size, and shifts right rsh.
(Note that I didn't rewrite hex to prepend zero at any time).
See if this does it:
>>> for i in xrange(36): print '%16s%16s' % (hex(kshr(-1L<<i,0)),hex(kshr(-1L<<i,1)))
...
0xFFL 0x7FL
0xFEL 0x7FL
0xFCL 0x7EL
0xF8L 0x7CL
0xF0L 0x78L
0xE0L 0x70L
0xC0L 0x60L
0x80L 0x40L
0xFF00L 0x7F80L
0xFE00L 0x7F00L
0xFC00L 0x7E00L
0xF800L 0x7C00L
0xF000L 0x7800L
0xE000L 0x7000L
0xC000L 0x6000L
0x8000L 0x4000L
0xFF0000L 0x7F8000L
0xFE0000L 0x7F0000L
0xFC0000L 0x7E0000L
0xF80000L 0x7C0000L
0xF00000L 0x780000L
0xE00000L 0x700000L
0xC00000L 0x600000L
0x800000L 0x400000L
0xFF000000L 0x7F800000L
0xFE000000L 0x7F000000L
0xFC000000L 0x7E000000L
0xF8000000L 0x7C000000L
0xF0000000L 0x78000000L
0xE0000000L 0x70000000L
0xC0000000L 0x60000000L
0x80000000L 0x40000000L
0xFF00000000L 0x7F80000000L
0xFE00000000L 0x7F00000000L
0xFC00000000L 0x7E00000000L
0xF800000000L 0x7C00000000L
>>> for i in xrange(36): print '%16s%16s' % (hex(kshr(+1L<<i,0)),hex(kshr(+1L<<i,1)))
...
0x1L 0x0L
0x2L 0x1L
0x4L 0x2L
0x8L 0x4L
0x10L 0x8L
0x20L 0x10L
0x40L 0x20L
0x80L 0x40L
0x100L 0x80L
0x200L 0x100L
0x400L 0x200L
0x800L 0x400L
0x1000L 0x800L
0x2000L 0x1000L
0x4000L 0x2000L
0x8000L 0x4000L
0x10000L 0x8000L
0x20000L 0x10000L
0x40000L 0x20000L
0x80000L 0x40000L
0x100000L 0x80000L
0x200000L 0x100000L
0x400000L 0x200000L
0x800000L 0x400000L
0x1000000L 0x800000L
0x2000000L 0x1000000L
0x4000000L 0x2000000L
0x8000000L 0x4000000L
0x10000000L 0x8000000L
0x20000000L 0x10000000L
0x40000000L 0x20000000L
0x80000000L 0x40000000L
0x100000000L 0x80000000L
0x200000000L 0x100000000L
0x400000000L 0x200000000L
0x800000000L 0x400000000L
Regards,
Bengt Richter
More information about the Python-list
mailing list