# Integer arithmetic

Bengt Richter bokr at oz.net
Sun Mar 30 01:01:20 CET 2003

```On Thu, 27 Mar 2003 07:11:40 GMT, Alex Martelli <aleax at aleax.it> wrote:

>Bengt Richter wrote:
>
>> On Wed, 26 Mar 2003 12:38:25 GMT, Alex Martelli <aleax at aleax.it> wrote:
>>>Daniel Timothy Bentley wrote:
>> [...]
>>>
>>>> Basically, if you're going to say ints and longs are separate types, I
>>>> think there should be a way to makes ints from longs fairly reliably.  I
>>>> don't think that's a niche, I think it's something a consistent language
>>>> should provice.
>>>
>>>Well, your proposed expression DOES "make ints from longs fairly
>>>reliably", it's just that I think the ints it makes are probably not the
>>>ones you'd like to get (except for 0<=foo<sys.maxint).
>>>
>>>I think you want something like: int(cmp(foo,0)*(abs(foo) & sys.maxint)).
>>>
>>>Me, I think it's better to incapsulate the "conversion to int ignoring
>>>overflow" in a function, using an if/else:
>>>
>>>def toint(foo):
>>>    if foo>=0: return int(foo&sys.maxint)
>>>    else: return -int(-foo&sys.maxint)
>>>
>> The above doesn't match typical hardware and C-style int behavior:
>
>Right, it doesn't replicate the asymmetry thus typically found.  You
>have to specialcase that.  In 2.2 it's easiest and fastest to:
>
>def toint(foo):
>    try: return int(foo)
>    except OverflowError: pass
>    if foo>=0: return int(foo&sys.maxint)
>    else: return -int(-foo&sys.maxint)
>
>but in 2.3 int(foo) won't raise OverflowError, so if you need to
>reproduce the asymmetry you can do something like:
>
>def toint(foo):
>    if foo==-sys.maxint-1: return int(foo)
>    elif foo>=0: return int(foo&sys.maxint)
>    else: return -int(-foo&sys.maxint)
>
>or you can swap the order of the first two guarded returns, if
>you like, since their guards are mutually exclusive of course:
>
>def toint(foo):
>    if foo>=0: return int(foo&sys.maxint)
>    elif foo==-sys.maxint-1: return int(foo)
>    else: return -int(-foo&sys.maxint)
>
>the second one is probably going to be marginally faster in
>practical use (fewer calls with -sys.maxint-1 than with >=0
>arguments), and another tiny performance enhancement is:
>
>    elif foo==anomaly: return int(foo)
>
>(probably too tiny to measure in most applications).
>
UIAM there's still a bug. I would model C behavior with

I.e., just mask off sufficient least significant bits of
the wider to fit in the narrower, including the sign bit,
and let the resulting sign bit be interpreted as a normal
sign bit irrespective of the further-up sign bit of the wider.

Note the difference for any positive long with a bit
in the int signbit position (ordinarily bit 31). Indeed,
just the positive long value of 1L<<31 itself will do it.

E.g., using

====< toint.py >================================
import sys
elif foo==anomaly: return int(foo)

================================================

>>> import sys
>>> import toint
>>> signbit = long(sys.maxint)+1
>>> signbit
2147483648L
>>> hex(signbit)
'0x80000000L'
>>> toint.toint_a(signbit)
0
>>> toint.toint_b(signbit)
-2147483648
>>> toint.toint_a(+1+signbit)
1
>>> toint.toint_b(+1+signbit)
-2147483647

Or as first mentioned,
>>> toint.toint_a(1L<<31)
0
>>> toint.toint_b(1L<<31)
-2147483648

Regards,
Bengt Richter

```