This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: Inconsistent Behavior of int()
Type: behavior Stage: resolved
Components: Build, Documentation, IDLE, Library (Lib), Windows Versions: Python 3.9
process
Status: closed Resolution: not a bug
Dependencies: Superseder:
Assigned To: docs@python Nosy List: Dennis Sweeney, TheDoctor165, docs@python, paul.moore, serhiy.storchaka, steve.dower, steven.daprano, terry.reedy, tim.golden, zach.ware
Priority: normal Keywords:

Created on 2021-08-08 17:49 by TheDoctor165, last changed 2022-04-11 14:59 by admin. This issue is now closed.

Files
File name Uploaded Description Edit
function_int_08Aug21.txt TheDoctor165, 2021-08-08 17:49 text in comment, not sure if I should have documented in comment or just attached a file
Messages (6)
msg399224 - (view) Author: John Joseph Morelli (TheDoctor165) Date: 2021-08-08 17:49
I first noticed this and reported it on the W3 Schools Tutorial, the section entitled "Add Two Numbers with User Input"

There were many behaviors that I did not understand, but for this bug report, I will state that the input statements present seem to return a string and under most situations will return an error if the user inputs a real number like 2.8.  However, under a very specific situation, it will truncate 2.8 to 2 without error.  

After further investigation, I believe the following session in the IDLE's output window  and editor illustrates this inconsistent behavior.  Note that I have added comments after copying the session here...

>>> print(x)  #want to ensure new session has x as undefined
Traceback (most recent call last):
  File "<pyshell#23>", line 1, in <module>
    print(x)
NameError: name 'x' is not defined  # confirmed x is undefined
>>> x="2" # define x as the string "2"
>>> print(x)
2
>>> print(type(x)) # confirm that x is a string value of "2" 
<class 'str'>
>>> y=int(x) # convert string value of "2" to integer of 2  -
# according to documentation this should work - see "If x is not a 
# number or if base is given, then x must be a string, bytes, or
# bytearray instance representing an integer literal in radix base."
# at link --> https://docs.python.org/3.9/library/functions.html#int
>>> print(type(y)) # ensure y is type int
<class 'int'>
>>> print(y)
2
>>> z=x+".8" # create z to be the concatenation of two strings "2" and ".8" = "2.8", a string representation of the real number 2.8
>>> print(z)
2.8
>>> print(type(z)) # ensure z is a string
<class 'str'>
>>> aa=int(z) # convert z to an integer (as descried in the link
# above, this should NOT work
Traceback (most recent call last):
  File "<pyshell#34>", line 1, in <module>
    aa=int(z)
ValueError: invalid literal for int() with base 10: '2.8'
>>> w="2.8" # Define w directly as the string value of 2.8 = "2.8"
>>> bb=int(w) # This should also produce an error
Traceback (most recent call last):
  File "<pyshell#36>", line 1, in <module>
    bb=int(w)
ValueError: invalid literal for int() with base 10: '2.8'
>>> a='2.8'
>>> b=int(a)
Traceback (most recent call last):
  File "<pyshell#38>", line 1, in <module>
    b=int(a)
ValueError: invalid literal for int() with base 10: '2.8'
>>> print(type(a)) # Ensure a is a string
<class 'str'>
>>> w="2"
>>> bb=int(w)
>>> print(bb)
2

>>> print(type(bb))
<class 'int'>
>>> test=int(input("What is test value? ")) #lets try inputting a
# real number but as an argument to int and assigning it to test
What is test value? 2.8 # this should not work either
Traceback (most recent call last):
  File "<pyshell#46>", line 1, in <module>
    test=int(input("What is test value? "))
ValueError: invalid literal for int() with base 10: '2.8'
>>> # So everything here is working as expected, but...

Here is code from the IDLE editor... a file called testinput1.py

x = int(1)
y = input("Type a number: ")
print(type(y))
int_y = int(2.8) #conver y to an integer 2 and assign to int_y
z = int("3")
print(x)
print(y)
print(int_y)
print(z)

# I can find no documentation to suggest this should work, but it does.  Here is the output in IDLE's shell

Type a number: 2.8
<class 'str'>
1
2.8
2
3

Now, if I immediately go into the shell while the variables remain untouched and defined...

>>> a=int(y) # Correctly, this produces the expected error
Traceback (most recent call last):
  File "<pyshell#47>", line 1, in <module>
    a=int(y)
ValueError: invalid literal for int() with base 10: '2.8'

After extensive testing, I conclude that after input, you may immediately apply the int() function to the resulting string, but you quickly lose that ability, resulting in the expected error.  I can find no documentation to explain this behavior.  

If I am not overlooking something, I think this should either be in the documentation of the function int(), if it is intended to behaviour this way, or as a bug, should be corrected.

NOTE, I just started learning Pytyon this weekend, so I may be just ignorant of the behavior, but I have searched a good bit and found nothing suggesting this is how int() should behalf.  I have also not studied the other constructor functions.
msg399225 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2021-08-08 18:03
Following your long example, it seems to me that all works as you expected. Raise an exception if you expect exception, and does raise it if you expect no exception.

I may miss something, what exactly does not work as you expected?
msg399229 - (view) Author: Dennis Sweeney (Dennis Sweeney) * (Python committer) Date: 2021-08-08 18:16
You typed `int_y = int(2.8)`, so you passed the floating point number 2.8, which the int() function rounds down to 2.

On the other hand when y had the string value '2.8'. The int(y) call tried to parse an integer out of the string, but failed since there were numbers after the decimal point.

Passing a float rounds down:

    >>> int(2.8)
    2

Passing a string with numbers after the decimal raises ValueError:

    >>> int('2.8')
    ValueError: invalid literal for int() with base 10: '2.8'

Passing a string of digits without a decimal correctly parses an integer:

    >>> int('42')
    42

Note that the input() function always returns a string, so input() can return '2.8', but not 2.8.
msg399232 - (view) Author: Steven D'Aprano (steven.daprano) * (Python committer) Date: 2021-08-08 19:02
John, there's no need to establish every feature in Python that you are **not** questioning. Please focus on the behaviour that you think is a bug. Pretty much nothing in your example before the line "So everything here is working as expected" is necessary. We're experienced Python users, some of us have been using Python for 20 years or more. We know how int() operates, you don't have to teach us.

What you have done is confuse the string '2.8' and the float 2.8, which is easy enough to do as a beginner. The critical error is this line:

    int_y = int(2.8) #conver y to an integer 2 and assign to int_y

But that's not converting the variable `y` to an integer, it is converting the float 2.8 to an integer. 2.8 is already a number, and calling int(2.8) drops the fractional part leaving 2 as expected.

Had you tried `int_y = int(y)` instead (y being a string) you would have got the exact error you were expecting.

It takes a little while to completely understand the differences between strings, ints, floats, literal numbers like 2.8 versus strings like "2.8", but that will come with some practice.

In future, rather than posting on the bug tracker, please consider asking questions on one of the many forums where volunteers will answer your questions and leave the bug tracker for actual bugs.

(Hint: there are many tens of thousands of Python programmers with collectively thousands of years of experience with the language. As a beginner with only a few days experience, you are highly unlikely to spot a bug that everyone else has missed.)

You can try the Python Discussion area:

https://discuss.python.org/


or the Python-List or Tutor mailing lists:

https://mail.python.org/mailman/listinfo/python-list

https://mail.python.org/mailman/listinfo/tutor


Good luck!
msg399233 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2021-08-08 19:11
John, for next time, please read 
https://stackoverflow.com/help/minimal-reproducible-example
msg399236 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2021-08-08 19:31
I understand your confusion John.

The fact is that int() serves two functions. If argument is a number, it truncates it to an integer. If argument is a string, it parses the string representation of integer (not necessary decimal).

For details see https://docs.python.org/3/library/functions.html#int .
History
Date User Action Args
2022-04-11 14:59:48adminsetgithub: 89029
2021-08-08 19:31:10serhiy.storchakasetmessages: + msg399236
2021-08-08 19:11:50terry.reedysetmessages: + msg399233
2021-08-08 19:03:53steven.dapranosetstatus: open -> closed
resolution: not a bug
stage: resolved
2021-08-08 19:02:33steven.dapranosetnosy: + steven.daprano
messages: + msg399232
2021-08-08 18:16:45Dennis Sweeneysetnosy: + Dennis Sweeney
messages: + msg399229
2021-08-08 18:03:36serhiy.storchakasetnosy: + serhiy.storchaka
messages: + msg399225
2021-08-08 17:49:51TheDoctor165create