Floating point calculation problem

Steven D'Aprano steve+comp.lang.python at pearwood.info
Sat Feb 2 12:45:38 CET 2013


Schizoid Man wrote:

> "Chris Angelico" <rosuav at gmail.com> wrote in message
> news:mailman.1289.1359801291.2939.python-list at python.org...
>> On Sat, Feb 2, 2013 at 9:27 PM, Schizoid Man <schiz_man at 21stcentury.com>
>> wrote:
>>> The quantity s is input with the following line: s = input("Enter s:  
>>> ")
>>>
>>> To get rid of the compile error, I can cast this as a float: s =
>>> float(input("Enter s:   "))
>>>
>>> However, then the result returned by the method is wrong. Why does this
>>> error occur in version 3.3.0 but not in 2.7.3? Why is the result
>>> incorrect
>>> when s is cast as a float (the casting is not required in 2.7.3)? How is
>>> Python dynamically typed if I need to cast (in version 3.3.0 at least)
>>> to get rid of the compile error?
>>
>> Did you use input() or raw_input() in 2.7.3? If the former, you were
>> actually doing this:
>>
>> s = eval(input("Enter s:  "))
>>
>> That's extremely dangerous and inadvisable, so it's better to go with
>> 3.3 or the raw_input function.
> 
> Thanks for the reply. You're right - even in 2.7.3 if I toggle between
> float(input(x)) and input(x), the result of the calculation changes. 

Highly unlikely. I'd say impossible, unless you type a different value for x
of course. By the time the input() function returns, the result is already
a float. Wrapping it in float() again cannot possibly change the value. If
you have found a value that does change, please tell us what it is.

The only examples I can think of that will behave that way involve NANs and
INFs. If you don't know what they are, don't worry about it, and forget I
mentioned them. For regular floating point values, I can't think of any
possible way that float(input(x)) and input(x) could give different
results.


> What does the float cast do exactly?

float(x) converts x into a float.

- if x is already a float, it leaves it unchanged;

- if x is a string, it converts it to the nearest possible float;

- if x is some other numeric value (e.g. int, Decimal or Fraction, 
  but not complex) it converts it to the nearest possible float.


>> Passing it through float() is, most likely, the right way to do this.
>> But what do you mean by "the result... is wrong"? That's the bit to
>> look into.
> 
> Scratch that, I'm not sure which result is right now, so need to look at
> the full calculations in details. What would be the difference between
> raw_input() and float(input())?

In Python 2.x, raw_input returns a string. To turn it into a float, you need
to use float(raw_input()).

float(input()) is a waste of time. The dangerous part happens in the call to
input(): a malicious user could type a Python command, and run arbitrary
code; or they could type something like "10**100**100" and lock up your
computer. Calling float *after* the call to input doesn't do anything.

In Python 3.x, raw_input is gone, but float(input()) is safe -- it is
exactly equivalent to float(raw_input()) in Python 2.x.

One other difference between Python 2.7 and 3.3 is that they sometimes
display floats slightly differently. Sometimes 3.3 will show more decimal
places:

[steve at ando ~]$ python2.7 -c "x = 1.0/33; print (x+x+x)"
0.0909090909091
[steve at ando ~]$ python3.3 -c "x = 1.0/33; print (x+x+x)"
0.09090909090909091

but you can be sure that they are the same value, it is just a difference in
the default display of floats:

[steve at ando ~]$ python2.7 -c "x = 1.0/33; print (x+x+x).hex()"
0x1.745d1745d1746p-4
[steve at ando ~]$ python3.3 -c "x = 1.0/33; print((x+x+x).hex())"
0x1.745d1745d1746p-4



-- 
Steven




More information about the Python-list mailing list