Rationale for core Python numeric types

P

Peter Hickman

Grant said:
I disagree.

Things like "eight-bit signed 2's compliment binary number"
have completely rigorous definitions that are not dependent on
some particular hardware platform.

What you say is true but the OP does not talk about "eight-bit signed 2's
compliment binary number", he talks about "e.g., single-precision
float, short integers". It is these types that the OP was talking about and
which I addressed.
No, I think you're missing the point. We're talking about
writing a Python program who's purpose is to manipulate
externally defined data in externally defined ways. The data
are binary numbers of specific lengths (typically 8, 16, and 32
bits) and the operations are things like 1's compliment, 2's
compliment, 2's compliment addition and subtraction, left and
right shift, binary and and or, etc.

Again returning to the OP, I find no mention of "things like 1's compliment, 2's
compliment, 2's compliment addition and subtraction, left and right shift,
binary and and or, etc". Am I missing a post or are you in private conversation
with the OP?

Besides I have not read from the OP what the program is to manipulate external
data in any special fashion. All my programs read external data, manipulate it
and write it out in external formats. I use my PowerPC to run programs that read
and write data from Intel boxes in a format that works for the Intel boxes. I
think that fits your description.
You seem obsessed with hardware. :)

The type system, or at least the whole zoo of integers, came about from the
hardware. First there was char and int, because there was only 8 bits anyway and
they were words. Then came 16 bits and the int went up to 16 bits but was now no
longer a synonym for char so we got short int and the cpus started to implement
signing of integers so now we require signed and unsigned integers. The whole
type system came into existence solely to allow access to the feature that cpus
provided.

Python (and Perl, Ruby, Java, etc., etc.) run within VMs of sorts and as such
the language only needs to know about the types that the VM provides not the
types that the cpu provides.
However, don't try to tell me that I don't
_need_ to use fixed-length binary 2's compliment numbers.

I have said nothing of the sort, perhaps you should read my post again.
Don't care about hardware -- at least not the hardware on which
I'm running Python.

Fine, but back the the OP. "I'm new to Python, and was somewhat taken aback to
discover that the core language lacks some basic numerical types (e.g.,
single-precision float, short integers)."

That is what I was answering, the why Python lacks the numerical types such as
single-precision float and short integers that are found in other earlier
languages and I felt that a little history as to why the type system came about
would go some way to aiding understanding.
 
G

Grant Edwards

What you say is true but the OP does not talk about "eight-bit signed 2's
compliment binary number", he talks about "e.g., single-precision
float, short integers". It is these types that the OP was talking about and
which I addressed.

You're right. I read more into his post that I should have.
When he wrote single-precision float, I assumed he meant 32-bit
IEEE-754, and "short int" he meant "16-bit signed 2's
compliment number".
Again returning to the OP, I find no mention of "things like
1's compliment, 2's compliment, 2's compliment addition and
subtraction, left and right shift, binary and and or, etc". Am
I missing a post or are you in private conversation with the
OP?

No -- something about the language he used made me think he was
working in the context I described: where one needs to perform
operations on types of specific lengths. You're right, though,
he didn't actually say that.
The type system, or at least the whole zoo of integers, came
about from the hardware. First there was char and int, because
there was only 8 bits anyway and they were words. Then came 16
bits and the int went up to 16 bits but was now no longer a
synonym for char so we got short int and the cpus started to
implement signing of integers so now we require signed and
unsigned integers. The whole type system came into existence
solely to allow access to the feature that cpus provided.

Agreed.
 
M

Michael Hudson

Grant Edwards said:
For much of what I do with Python, fixed width integers would
be awfully nice -- then I wouldn't have to and everything with
0xff, 0xffff, or 0xffffffff to get the results I want.

Last time I did bit bashing in Python I ended up writing this:

"""Traceback (most recent call last):
File \"<stdin>\", line 1, in ?
File \"field.py\", line 25, in encode
raise ValueError(\"field '%s' can't accept value %s\"
ValueError: field 'test' can't accept value 65536
"""


class Field(object):
def __init__(self, name, left, right, signedness=False, valclass=int):
self.name = name
self.left = left
self.right = right
width = self.right - self.left + 1
# mask applies before shift!
self.mask = 2**width - 1
self.signed = signedness == 'signed'
self.valclass = valclass
def __repr__(self):
return '<Field %r>'%(self.name,)
def encode(self, value):
if not issubclass(self.valclass, type(value)):
raise ValueError("field '%s' takes '%s's, not '%s's"
%(self.name, self.valclass.__name__, type(value).__name__))
if not self.signed and value < 0:
raise ValueError("field '%s' is unsigned and can't accept value %d"
%(self.name, value))
# that this does the right thing is /not/ obvious (but true!)
if ((value >> 31) ^ value) & ~(self.mask >> self.signed):
raise ValueError("field '%s' can't accept value %s"
%(self.name, value))
value &= self.mask
value = long(value)
value <<= (32 - self.right - 1)
if value & 0x80000000L:
# yuck:
return ~int((~value)&0xFFFFFFFFL)
else:
return int(value)
def decode(self, inst):
mask = self.mask
v = (inst >> 32 - self.right - 1) & mask
if self.signed and (~mask >> 1) & mask & v:
v = ~(~v&mask)
return self.valclass(v)

if __name__=='__main__':
import doctest
doctest.testmod()

parts of which are pretty painful, but in usage it's probably neater
than what I would have ended up with if Python *did* have fixed width
integers... (this is from my PPC assembler, which might explain some
of the variable names and why bit 0 is the most significant).

Cheers,
mwh
 
J

Josef Dalcolmo

Python longs are 2's-complement with a conceptually infinite number of
sign bits (whether 0 or 1). So ~0 will be, like ~0L today, an
infinite string of 1 bits. Even today:

True


Ok, so using longs should be the way of the future in Python, but unfortunately trying to pass to fcntl.fcntl an argument of type long fails with a message saying it can take only int's. When I define an int where the MSB (of 32 bits) is set, I get a deprecation warning. I guess the module fcntl needs some updating.

- Josef
 
M

Michael Hudson

Josef Dalcolmo said:
Ok, so using longs should be the way of the future in Python, but
unfortunately trying to pass to fcntl.fcntl an argument of type long
fails with a message saying it can take only int's. When I define an
int where the MSB (of 32 bits) is set, I get a deprecation
warning. I guess the module fcntl needs some updating.

Weird. What version of Python? Can you paste an example? I can
successfully pass longs to fcntl and ioctl on my machine with Python
2.3.3...

Cheers,
mwh
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,202
Messages
2,571,057
Members
47,665
Latest member
salkete

Latest Threads

Top