views:

206

answers:

3

You can skip to the bottom line if you don't care about the background:

I have the following code in Python:

ratio = (point.threshold - self.points[0].value) / (self.points[1].value - self.points[0].value)

Which is giving me wrong values. For instance, for:

threshold:  25.0
self.points[0].value:  46
self.points[1].value:  21

I got:

ratio:  -0.000320556853048

Which is wrong.

Looking into it, I realized that self.points[0].value and self.points[1].value] are of the type numpy.uint16`, so I got:

21 - 46 = 65511

While I never defined a type for point.threshold. I just assigned it. I imagine it got a plain vanilla int.

The Bottom Line

How can I force the the subtraction of two uints to be signed?

+2  A: 

Well, the obvious solution would probably be to cast to floats:

ratio = (float(point.threshold) - float(self.points[0].value)) / (float(self.points[1].value) - float(self.points[0].value))

Or I suppose you could cast to one of the numpy signed types.

David Zaslavsky
+2  A: 

Almost anything but uints will work here, so just cast these to something else before you do the subtraction.

Since threshold = 25.0 (note the decimal point), it's a float, so the subtraction and division will all work as long as you're not using uints.

tom10
A: 

Do those values actually NEED to be uint16 instead of int16? Unless they have to be able to take values of 2**15 or above (but still below 2**16) you could simply keep them as int16 and be done with it -- unsigned ints, as you discovered, can be tricky (and not just in numpy;-). If you DO need the uint16, then casts as David suggests will work, but if you can simply use int16 it will be faster and more readable.

BTW, it looks like that point.threshold is a float, not an int (good thing too, otherwise that division the way you code it would be a truncating one, unless you're importing true division from the future, as has been supported in many 2.* releases of Python -- and is finally THE way division works in 3.*). The .0 in 25.0 "gives it away" and shows it's a float, not an int.

Alex Martelli
I'm reading the data from a binary file where the data is in uint16 format. I imported true division from the future, too
Nathan Fellman
But do they NEED to be unsigned, i.e., do they actually TAKE values between `2**15` and `2**16`? Otherwise there is no difference between binary format for unsigned vs signed integers.
Alex Martelli