Python Forum
Something is wrong with my logic in this program
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Something is wrong with my logic in this program
#1
Hi!

First, I made a small program to draw a poligon whose number of sides is entered by the user:

# mawp_01_choosepoligon_01.py
#
# It works!

from turtle import *

speed(0)
nsides = input("Enter the number \
(bigger than 2) of sides of your \
desired poligon.\n")

ang1 = 360/int(nsides)
def poligon(sidelength=100):
    for i in range(int(nsides)):
        forward(sidelength)
        right(ang1)
poligon()
and it works:
Output:
Enter the number (bigger than 2) of sides of your desired poligon. 7 >>>
[Image: poligon-07-sides.png]

Output:
Enter the number (bigger than 2) of sides of your desired poligon. 12 >>>
[Image: poligon-12-sides.png]

Then I decided to complicate things a little more (going from simpler to more complex), by preventing the user to enter letters, negative numbers or decimal numbers (with a 'decimal separator' like '.' or ','), but then I have already encountered problems (I haven't coded yet from preventing entering letters). My program is now like this:

# mawp_01_choosepoligon_02.py
#
# It doesn't work yet.

from turtle import *

speed(0)
nsides = input("\nEnter the number \
(bigger than 2) of sides of your \
desired poligon.\n")

while "." in nsides or "," in nsides:
    nsides = input("\nDo you think a poligon can have half a side?\n\
Please, enter the number \
(bigger than 2) of sides of your \
desired poligon.\n")        
        
if "." not in nsides and "," not in nsides:
    while nsides < '3':
        nsides = input("\nPlease, enter the number \
(bigger than 2) of sides of your \
desired poligon.\n")    

    if nsides >= '3':
        ang1 = 360/int(nsides)
        for i in range(int(nsides)):
            forward(75)
            right(ang1)
but when I checked with a few numbers, I get this:
Output:
Enter the number (bigger than 2) of sides of your desired poligon. 1 Please, enter the number (bigger than 2) of sides of your desired poligon. 2 Please, enter the number (bigger than 2) of sides of your desired poligon. -1 Please, enter the number (bigger than 2) of sides of your desired poligon. 0 Please, enter the number (bigger than 2) of sides of your desired poligon. 2.5 Please, enter the number (bigger than 2) of sides of your desired poligon. 3.5
Error:
Traceback (most recent call last): File "C:\Users\User1\AppData\Local\Programs\Python\Python37\mawp_01_choosepoligon_02.py", line 25, in <module> ang1 = 360/int(nsides) ValueError: invalid literal for int() with base 10: '3.5'
So I think something must be wrong with my logic in this program. I wrote the program, thinking that while a number with a decimal separator (a number having a '.' or a ',' covering the use of ',' in most countries in Europe), the program would keep asking until a number with no decimal separator is entered (lines 12-16):

while "." in nsides or "," in nsides:
    nsides = input("\nDo you think a poligon can have half a side?\n\
Please, enter the number \
(bigger than 2) of sides of your \
desired poligon.\n")
Otherwise, if a number with no decimal separator is entered, line 18 would run:

if "." not in nsides and "," not in nsides:
and then, if the number is < '3' (lines 19-22), the program would keep asking until a number >= '3' is entered:

    while nsides < '3':
        nsides = input("\nPlease, enter the number \
(bigger than 2) of sides of your \
desired poligon.\n")
If the number entered is >= '3', line 24 would run:

    if nsides >= '3':
then the inner block would run, lines 25-28:

        ang1 = 360/int(nsides)
        for i in range(int(nsides)):
            forward(75)
            right(ang1)
So I don't understand why:

1) When I entered 2.5 (having '.' in the input) the code that is executed is lines 18-22:

if "." not in nsides and "," not in nsides:
    while nsides < '3':
        nsides = input("\nPlease, enter the number \
(bigger than 2) of sides of your \
desired poligon.\n")
instead of lines 12-16:

while "." in nsides or "," in nsides:
    nsides = input("\nDo you think a poligon can have half a side?\n\
Please, enter the number \
(bigger than 2) of sides of your \
desired poligon.\n") 
2) When I entered 3.5 (having '.' in the input) the code that is executed is lines 24-28:

    if nsides >= '3':
        ang1 = 360/int(nsides)
        for i in range(int(nsides)):
            forward(75)
            right(ang1)
instead of lines 12-16:

while "." in nsides or "," in nsides:
    nsides = input("\nDo you think a poligon can have half a side?\n\
Please, enter the number \
(bigger than 2) of sides of your \
desired poligon.\n")
3) Regardless of my thoughts in question 2), why is that int(3.5) produces an error? Shouldn't int(3.5) produce '3'?

4) I thought that Python runs linearly, I mean line 1 is run previously to line 2, and this line 2 previously to line 3, and so on. So am I wrong on this? That's also why I'm clueless about this problem .

Any ideas would be appreciated, thanks.

All the best,
newbieAuggie2019

"That's been one of my mantras - focus and simplicity. Simple can be harder than complex: You have to work hard to get your thinking clean to make it simple. But it's worth it in the end because once you get there, you can move mountains."
Steve Jobs
Reply
#2
Here's what's going on: first you get a number that is not a decimal. Then you get a number that is at least 3. The problem is that these two things are separate. So you enter '1', and it validates that as not a decimal. So then it starts to check for at least 3. At this point it is no longer checking for decimals. That part of your code is done executing, and there is nothing to bring it back there. It just keeps going through the second while loop, not even checking the first if statement. So when you enter 3.5 (after entering 1), it (sort of) validates that as greater than 3, and goes ahead and tries to make an int out of it.

What you need is one while loop where you keep checking the input until all of your criteria are met, and then you do your business. You might want to check out the tutorial on validating user input, it covers how to do this sort of thing in detail.

Now, I said your program "sort of" validates that the number is less than 3. The problem is that you are comparing strings ('3.5' and '3', rather than 3.5 and 3). String compare in ASCII order, not in numeric order. So any string starting with a '1' or a '2' is less than a string starting with a '3'. That means '10' is less than '3' (and '32' is less than '5'). So you need to check for a number, convert to a number, and then check for the number being in the right range.
Craig "Ichabod" O'Brien - xenomind.com
I wish you happiness.
Recommended Tutorials: BBCode, functions, classes, text adventures
Reply
#3
Thanks a lot for your very clear and didactic answer!!!

(Sep-30-2019, 04:58 PM)ichabod801 Wrote: Here's what's going on: first you get a number that is not a decimal. Then you get a number that is at least 3. The problem is that these two things are separate. So you enter '1', and it validates that as not a decimal. So then it starts to check for at least 3. At this point it is no longer checking for decimals. That part of your code is done executing, and there is nothing to bring it back there.

I had thought wrongly that every single input would have made run the program from the beginning.

(Sep-30-2019, 04:58 PM)ichabod801 Wrote: It just keeps going through the second while loop, not even checking the first if statement. So when you enter 3.5 (after entering 1), it (sort of) validates that as greater than 3, and goes ahead and tries to make an int out of it.

That's something that still I don't understand, because if I enter int(3.5), I get the following output:
Output:
>>> int(3.5) 3
I thought that that would have converted the string '3.5' into an integer, therefore, 3 instead of 3.5.

(Sep-30-2019, 04:58 PM)ichabod801 Wrote: What you need is one while loop where you keep checking the input until all of your criteria are met, and then you do your business. You might want to check out the tutorial on validating user input, it covers how to do this sort of thing in detail.

Wonderful! Thanks again for such a great tutorial!!!

(Sep-30-2019, 04:58 PM)ichabod801 Wrote:
Output:
Please enter an integer: Fred Fred is not an integer.
Now, obviously Fred is not an integer. It may not be polite to say this about Fred, but it is unfortunately true.

LOL Surfing Big Grin Clap

(Sep-30-2019, 04:58 PM)ichabod801 Wrote: Now, I said your program "sort of" validates that the number is less than 3. The problem is that you are comparing strings ('3.5' and '3', rather than 3.5 and 3). String compare in ASCII order, not in numeric order. So any string starting with a '1' or a '2' is less than a string starting with a '3'. That means '10' is less than '3' (and '32' is less than '5'). So you need to check for a number, convert to a number, and then check for the number being in the right range.

Once again, I wrongly thought that comparing 10 < 3 would mean the same as '10' < '3', when comparing values of numbers.
Output:
>>> 10 < 3 False >>> '10' < '3' True
I didn't know that either.

So following your great tutorial (although I still don't fully understand try/except blocks), I changed my program to this:

# mawp_01_choosepoligon_03.py
#
# It finally works! HOORAY!!!

from turtle import *


speed(0)

while True:
    nsides = input("\nEnter a whole number \
(bigger than 2) of sides of your \
desired poligon.\n")
    if nsides.isdigit() and int(nsides) >= 3:
        number = int(nsides)
        break
    print('{} is not a whole number \
bigger than 2.'.format(nsides))

ang1 = 360/number
for i in range(number):
    forward(75)
    right(ang1)
so so so much simpler and nicer code, with the following output:
Output:
Enter a whole number (bigger than 2) of sides of your desired poligon. 1 1 is not a whole number bigger than 2. Enter a whole number (bigger than 2) of sides of your desired poligon. -1 -1 is not a whole number bigger than 2. Enter a whole number (bigger than 2) of sides of your desired poligon. -1.5 -1.5 is not a whole number bigger than 2. Enter a whole number (bigger than 2) of sides of your desired poligon. 2 2 is not a whole number bigger than 2. Enter a whole number (bigger than 2) of sides of your desired poligon. Monty Python Monty Python is not a whole number bigger than 2. Enter a whole number (bigger than 2) of sides of your desired poligon. 2.5 2.5 is not a whole number bigger than 2. Enter a whole number (bigger than 2) of sides of your desired poligon. 3.5 3.5 is not a whole number bigger than 2. Enter a whole number (bigger than 2) of sides of your desired poligon. 3 >>>
[Image: poligon-03-sides.png]
Output:
Enter a whole number (bigger than 2) of sides of your desired poligon. 6 >>>
[Image: poligon-06-sides.png]

Once again, thank you very much indeed for your very useful and pedagogical explanation!!!
I have learned quite a few of very interesting bits of logic and Python with this problem!

All the best,
newbieAuggie2019

"That's been one of my mantras - focus and simplicity. Simple can be harder than complex: You have to work hard to get your thinking clean to make it simple. But it's worth it in the end because once you get there, you can move mountains."
Steve Jobs
Reply
#4
(Sep-30-2019, 06:23 PM)newbieAuggie2019 Wrote: That's something that still I don't understand, because if I enter int(3.5), I get the following output:

Output:
>>> int(3.5)
3

I thought that that would have converted the string '3.5' into an integer, therefore, 3 instead of 3.5.

I have wondered about that myself from time to time. I don't really have a good explanation for it.
Craig "Ichabod" O'Brien - xenomind.com
I wish you happiness.
Recommended Tutorials: BBCode, functions, classes, text adventures
Reply
#5
(Sep-30-2019, 06:43 PM)ichabod801 Wrote:
(Sep-30-2019, 06:23 PM)newbieAuggie2019 Wrote: That's something that still I don't understand, because if I enter int(3.5), I get the following output:

Output:
>>> int(3.5)
3

I thought that that would have converted the string '3.5' into an integer, therefore, 3 instead of 3.5.

I have wondered about that myself from time to time. I don't really have a good explanation for it.

Think Could it be a bug inside Python code??? Blush
newbieAuggie2019

"That's been one of my mantras - focus and simplicity. Simple can be harder than complex: You have to work hard to get your thinking clean to make it simple. But it's worth it in the end because once you get there, you can move mountains."
Steve Jobs
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Am I wrong or is Udemy wrong? String Slicing! Mavoz 3 2,387 Nov-05-2022, 11:33 AM
Last Post: Mavoz
  python gives wrong string length and wrong character thienson30 2 2,943 Oct-15-2019, 08:54 PM
Last Post: Gribouillis

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020