[Tutor] Limitation of int() in converting strings

Steven D'Aprano steve at pearwood.info
Sat Dec 22 02:34:42 CET 2012


On 18/12/12 01:36, Oscar Benjamin wrote:

> I think it's unfortunate that Python's int() function combines two
> distinct behaviours in this way. In different situations int() is used
> to:
> 1) Coerce an object of some type other than int into an int without
> changing the value of the integer that the object represents.

The second half of the sentence (starting from "without changing") is not
justified. You can't safely make that assumption. All you know is that
calling int() on an object is intended to convert the object to an int,
in whatever way is suitable for that object. In some cases, that will
be numerically exact (e.g. int("1234") will give 1234), in other cases it
will not be.


> 2) Round an object with a non-integer value to an integer value.

int() does not perform rounding (except in the most generic sense that any
conversion from real-valued number to integer is "rounding"). That is what
the round() function does. int() performs truncating: it returns the
integer part of a numeric value, ignoring any fraction part:

py> from decimal import Decimal as D
py> from fractions import Fraction as F
py> int(D("-123.99999999"))
-123
py> int(F(999, 100))
9


So you shouldn't think of int(number) as "convert number to an int", since
that is ambiguous. There are at least six common ways to convert arbitrary
numbers to ints:

* truncate, or round towards zero (drop any fraction part);

* floor, or round towards -infinity (always round down);

* ceiling, or round towards +infinity (always round up);

* round to nearest, with ties rounding up;

* round to nearest, with ties rounding down;

* banker's rounding (round to nearest, with ties rounding to the
   nearest even number)

Python provides truncation via the int and math.trunc functions, floor and
ceiling via math.floor and math.ceil, and round to nearest via round.
In Python 2, ties are rounded up, which is biased; in Python 3, the
unbiased banker's rounding is used.

Instead, you should consider int(number) to be one of a pair of functions,
"return integer part", "return fraction part", where unfortunately the
second function isn't provided directly. In general though, you can get
the fractional part of a number with "x % 1". For floats, math.modf also
works.

So, in a sense int() does to double-duty as both a constructor of ints
from non-numbers such as strings, and as a "get integer part" function for
numbers. I'm okay with that.



-- 
Steven


More information about the Tutor mailing list