is int(round(val)) safe?

Bengt Richter bokr at oz.net
Mon Nov 22 23:46:35 EST 2004


On Mon, 22 Nov 2004 15:58:54 -0500, Peter Hansen <peter at engcorp.com> wrote:

>Russell E. Owen wrote:
>> I realize this probably a stupid question, but...is it safe to 
>> round to the nearest integer by using int(round(val))?
>
>Define "safe".
>
>> I suspect it is fine, but wanted to be sure that weird floating point 
>> representation on some platform might make it unsafe there (i.e. get the 
>> wrong value due to the floating point value being an approximation) and 
>> if so, is there a Better Way).
>
>Since round() returns an integer, and since (ignoring really
>large integers, since I doubt you're concerned about them
>here) floating point values can handle *integer* values
>perfectly well, there's no reason it shouldn't do what you
>want.
>
>The problem* with floating point is inaccurate representation
>of certain _fractional_ values, not integer values.

Well, you mentioned really large integers, and I think it's worth
mentioning that you can get inaccurate representation of certain of those
values too. I.e., what you really have (for ieee 754 doubles) is 53 bits
to count with in steps of one weighted unit, and the unit can be 2**0
or 2**otherpower, where otherpower has 11 bits to represent it, more or less
+- 2**10 with an offset for 53. If the unit step is 2**1, you get twice the range
of integers, counting by two's, which doesn't give you a way of representing the
odd numbers between accurately. So it's not only fractional values that can get
truncated on the right. Try adding 1.0 to 2.0**53 ;-)

 >>> 2.0**53
 9007199254740992.0
 >>> 2  **53 # just to check
 9007199254740992L
 >>> 2.0**53 + 1.0
 9007199254740992.0
 >>> 2  **53 + 1 # just to check
 9007199254740993L

The float gets rounded down, but you can count by two's

 >>> 2.0**53
 9007199254740992.0
 >>> 2.0**53 +2.0
 9007199254740994.0

(2.0**53-1.0 is the last number with a LSB value of 1.0, but you can add 1.0
to that and get an exact 2.0**53 because the unit bit that results is 0 so it
doesn't matter that it's to the right of the new LSB of 2.0**53 (which has a weight of 2.0)).

Another way of thinking about it is that it's not about the accuracy of the numbers,
it's about how far apart the available accurate number representations are and the
choice you have to make if the value you want to represent falls between.

>
>-Peter
>
>* Well, _one_ of the problems. ;-)

Regards,
Bengt Richter



More information about the Python-list mailing list