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