5

I am calculating the absolute difference between two numpy.uint8s in python with d = abs(a - b), which results in an overflow error if b is bigger than a. What's the best way to avoid this?

senderle
  • 145,869
  • 36
  • 209
  • 233
blues
  • 4,547
  • 3
  • 23
  • 39
  • 1
    Er... no it doesn't. Python automatically promotes integers to longs when necessary. Also, there's no unsigned integer type in Python. Please post code that demonstrates the problem you're actually having, and a traceback. – kindall Sep 26 '12 at 23:55
  • 2
    I get a and b from an external library (pygtk) and their type is numpy.uint8. The error is RuntimeWarning: overflow encountered in ubyte_scalars. Because of this it's not possible to give a short working example. – blues Sep 26 '12 at 23:58

3 Answers3

3

As your comment indicates, they aren't ints; they're numpy.uint8s. Just convert them to ints:

>>> a, b = map(numpy.uint8, (50, 60))
>>> a - b
__main__:1: RuntimeWarning: overflow encountered in ubyte_scalars
246
>>> a, b = map(int, (a, b))
>>> a - b
-10

Since you are concerned about speed, here are a couple of tests (borrowing Sven's form, with thanks):

>>> %timeit abs(int(a) - int(b))
1000000 loops, best of 3: 410 ns per loop
>>> %timeit a - b if a > b else b - a
1000000 loops, best of 3: 470 ns per loop

So yes, it's faster, but unless we're talking about doing it hundreds of millions of times, it won't matter a bit.

Community
  • 1
  • 1
senderle
  • 145,869
  • 36
  • 209
  • 233
  • Is this faster than the test Ionut suggested? Because I need to do this very often. – blues Sep 27 '12 at 00:07
  • @blues, if you have a numpy array of them (which looks a lot like a list with duck typing) you can get *much* faster probably, but if its just single values numpy can't help you with speed... – seberg Sep 27 '12 at 17:23
2

The easiest way is to manually convert your numbers to Python ints first:

d = abs(int(a) - int(b))

Python ints can't overflow (unless the memory is full).

Sven Marnach
  • 574,206
  • 118
  • 941
  • 841
0

For me it does not throw overflow error, just results in false values if b is bigger than a. To stay in uint8 boundaries use this function:

def abs_dev (a, b) :
    sub1 = a - b
    sub2 = b - a
    mask = a < b
    sub1[mask] = sub2[mask]
    return sub1
Mikhail V
  • 1,416
  • 1
  • 14
  • 23