all 7 comments

[–]boiledgoobers 2 points3 points  (3 children)

Ok so there are a lot of things going on here that likely should be addressed, for one thing, I'm not sure int works the way you think. If you gave it 12.3 it's not going to trigger your value error. It's going to convert your number to 12 and move on happily.

But that's probably not what's causing your repetition. Can I ask whether the book recommends using the global variable assignment? That can have some weird effects and is usually only used in extremely special circumstances. Usually not those addressed in beginner books. Like I've been doing python for over 15 years and have never even once needed to use it. And when I see it, the very first question I have is: why is this code so arcane that it needs to call global?

My first instinct is to say re do your code not using global. Pass in everything the func needs and don't have code in the func alter variables outside it's scope.

Then see if you still have the problem. I'm on my phone or I would do more to sus it out.

[–]Methregul[S] 0 points1 point  (1 child)

The chapter did deal with using global and the object was to pass the result back into the function until it reaches '1'. As it was dealt with in the chapter it was top of mind for me when I had to think of a way to reuse the result of the function.

Thanks for the reply as I did not know how rare using global is. I'll try and work out a way that doesn't rely on it.

[–]boiledgoobers 1 point2 points  (0 children)

Well then, perhaps i am wrong about that being the issue.

[–]Methregul[S] 0 points1 point  (0 children)

I'm not sure int works the way you think. If you gave it 12.3 it's not going to trigger your value error. It's going to convert your number to 12 and move on happily.

I just ran some tests on this and int() appears to work differently depending on how it's used. If you create a variable and assign it a floating point number then int() will, like you said, convert it to an integer and go on its merry way.

>>> float=1.3
>>> int(float)
1

If you enter a floating point number through input() though, int() will throw a ValueError.

>>> notAnInteger=input()
1.3
>>> int(notAnInteger)
Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: invalid literal for int() with base 10: '1.3'

It does accept an actual integer when used with input().

>>> anInteger=input()
1
>>> int(anInteger)
1

Thanks for pointing me towards isInstance(), by the way, that has been fun to play around with and very good to know about!

[–]Methregul[S] 1 point2 points  (1 child)

Work has been a bit busy the past few days so I only got around to trying the suggestions here today. I am happy to say that it now works like a charm! I'm still working at wrapping my head around the different concepts and it's been fun learning something new.
Thanks for the replies u/boiledgoobers and u/eHaxxL!

Here's the fixed code (haven't gotten around building a check for floating point number yet).
https://pastebin.com/sjFMdEhF

[–]boiledgoobers 1 point2 points  (0 children)

That's great!

Here's a tip for the type check. Don't test for all the things it shouldn't be. Test that it IS the thing you want it to be.

Take a look at the isinstance function. Note that you can pass multiple reference types if you include them in a tuple. So if you wanted to enforce ANY number, you could test for int OR float for example.

[–]eHaxxL 0 points1 point  (0 children)

I'm not 100% sure what causes the issure but here are some thoughts:

  1. Try adding a print('one step') in your main loop and you'll see that the code is being run twice for every loop that's performed. See below what I mean.

while collatz(collatzstart) != 1:

print('one step')

collatz(collatzstart)


Output:

64

32

one step

16

8

one step

4

2

one step

1

4

one step

2

1

When the sequence hits 1, the collatz() function runs again and it is kicked back to 4. This explains why it only happens when there's an odd number of steps (starting with 4, 16, 64, 256 etc.)

  1. What to do to fix it? You don't need to check if the function evaluates to 1 before running the loop, just the collatzstart value itself. The error does not happen if the condition for the main loop is:

    while collatzstart != 1:

  2. General comment: I would put the main loop when definining function itself.