int vs. float

Erik python at lucidity.plus.com
Sat Feb 11 17:33:53 EST 2017


[Dan, this isn't "aimed" at you personally, it's just a follow-up on the 
general point I am (and I think you are also) making]

On 11/02/17 02:17, Dan Sommers wrote:
> At least it works both ways:
>
> Python 3.5.3 (default, Jan 19 2017, 14:11:04)
> [GCC 6.3.0 20170118] on linux
> Type "help", "copyright", "credits" or "license" for more information.
>>>> s = "33333333333333333333333333333333333333333333333333333333333333333"
>>>> f = float(s)
>>>> i = int(s)

Yes, but Peter said "accept the number as a float, and then complain if 
int(num) != num.", so he meant use "i = int(f)" (i.e., convert the float 
to an int, not the original string).

Anyway, that's just as bad, but in a different way ;) Using your example:

Python 3.5.2 (default, Nov 17 2016, 17:05:23)
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
 >>> s = "33333333333333333333333333333333333333333333333333333333333333333"
 >>> f = float(s)
 >>> f
3.3333333333333333e+64
 >>> i = int(f)
 >>> i
33333333333333333069679542094544616940918707231410151788522766336
 >>> i == f
True
 >>>

That's poor if "i" ends up being the value actually used later when the 
input is processed - it's NOT the value the user entered!

I imagine that this particular use-case is not trying to teach the OP 
about float/int issues, but about how to parse numerical strings from 
user-input (so these extreme cases are not expected to be part of the 
input range). I might be wrong, though.

However, these sorts of issues are a very important consideration for 
people writing real-world code where the input might be coming from an 
external source such as a database or output from a language which uses 
fixed-point or some other precise representation of decimals (e.g., COBOL).

Whenever you convert something that may not be an integer in the 
appropriate range to a float (using IEEE 754, at least) you must be 
aware that you may lose precision. The answer in this case is to do 
something similar to what Peter suggested, but to use Python's 'decimal' 
type as the intermediate representation rather than the float() type:

Python 3.5.2 (default, Nov 17 2016, 17:05:23)
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
 >>> from decimal import Decimal as dec
 >>> s = "0.99999999999999995"
 >>> d = dec(s)
 >>> i = int(d)
 >>> d
Decimal('0.99999999999999995')
 >>> i
0
 >>> i == d
False
 >>> s = "33333333333333333333333333333333333333333333333333333333333333333"
 >>> d = dec(s)
 >>> i = int(d)
 >>> d
Decimal('33333333333333333333333333333333333333333333333333333333333333333')
 >>> i
33333333333333333333333333333333333333333333333333333333333333333
 >>> i == d
True


No surprises there ;)

E.



More information about the Python-list mailing list