While loop does not break though condition is met (Collatz Sequence) [duplicate] - python

This question already has answers here:
Implementing the collatz function using Python
(8 answers)
Closed 5 years ago.
Note: I was trying to figure out why my while statement did not evaluate to False when the integer was, so I don't believe this is a duplicate
Doing an automating the boring stuff exercise in python where the program receives an input and reduces it to 1 using the following algorithm.
#even / 2
#odd * 3 + 1
def collatz():
print("Enter number:")
number = input()
try:
data = int(number) # Input Validation
while int(data) != 1:
if data % 2 == 0: #Number is even
data = int(data/2)
print(data)
if data % 2 == 1: # Number is odd
data = int(3*data+1)
print(data)
except:
print("Please input a valid value")
collatz()
collatz()
Instead of the while loop breaking, when the number is reduced to 1. The loop continues and it multiplies 1 by 3 and adds 1(Just as normal odd number). Btw many int conversions were done as I thought it may have returned a floating point.
So please tell me where are the unncessary int conversions and how to break it using a while statement. Any cleanup to code is appreciated

There are a few things that you should neaten up to make your code work properly and just generally better:
Rename data to n, this isn't going to make much of a difference, but I would say it just makes more sense.
There is no need to do endless conversions to int, n only needs to be converted from a string to an integer once.
Don't put your entire code in a function then call it once, instead have the main algorithm in a smaller function which you then can call from the main body of your code or even create another function to call the algorithm which handles the inputting side of things.
Use the integer division operator (//) instead of the floating point divider (/), since the number will be even, you can be sure that the decimal place will be 0.
You don't need to check if n % 2 is 0 and then on the next line check if it n % 2 is 1, you can just use an if ... else clause.
And that's about it! Here's what it looks like:
#even / 2
#odd * 3 + 1
def collatz(n):
while n != 1:
if n % 2 == 0: #Number is even
n = n // 2
else:
n = n * 3 + 1
print(n)
number = input("Enter number:")
try:
number = int(number)
collatz(number)
except ValueError:
print("Please input a valid value")
And a test shows it works (input of 24):
12
6
3
10
5
16
8
4
2
1

Related

WAP in python script to input a multidigit number and find each of the number's factorial

The output shows a different result. Yes, the factorials of those numbers are right but the numbers outputted aren't right.
Here's the code:
input:
n = int(input("Enter a number: "))
s = 0
fact = 1
a = 1
for i in range(len(str(n))):
r = n % 10
s += r
n //= 10
while a <= s:
fact *= a
a += 1
print('The factorial of', s, 'is', fact)
Output:
Enter a number: 123
The factorial of 3 is 6
The factorial of 5 is 120
The factorial of 6 is 720
You're confusing yourself by doing it all in one logic block. The logic for finding a factorial is easy, as is the logic for parsing through strings character by character. However, it is easy to get lost in trying to keep the program "simple," as you have.
Programming is taking your problem, designing a solution, breaking that solution down into as many simple, repeatable individual logic steps as possible, and then telling the computer how to do every simple step you need, and what order they need to be done in to accomplish your goal.
Your program has 3 functions.
The first is taking in input data.
input("Give number. Now.")
The second is finding individual numbers in that input.
for character in input("Give number. Now."):
try:
int(character)
except:
pass
The third is calculating factorials for the number from step 2. I won't give an example of this.
Here is a working program, that is, in my opinion, much more readable and easier to look at than yours and others here. Edit: it also prevents a non numerical character from halting execution, as well as using only basic Python logic.
def factorialize(int_in):
int_out = int_in
int_multiplier = int_in - 1
while int_multiplier >= 1:
int_out = int_out * int_multiplier
int_multiplier -= 1
return int_out
def factorialize_multinumber_string(str_in):
for value in str_in:
print(value)
try:
print("The factorial of {} is {}".format(value, factorialize(int(value))))
except:
pass
factorialize_multinumber_string(input("Please enter a series of single digits."))
You can use map function to get every single digit from number:
n = int(input("Enter a number: "))
digits = map(int, str(n))
for i in digits:
fact = 1
a = 1
while a <= i:
fact *= a
a += 1
print('The factorial of', i, 'is', fact)
Ok, apart from the fact that you print the wrong variable, there's a bigger error. You are assuming that your digits are ever increasing, like in 123. Try your code with 321... (this is true of Karol's answer as well). And you need to handle digit zero, too
What you need is to restart the calculation of the factorial from scratch for every digit. For example:
n = '2063'
for ch in reversed(n):
x = int(ch)
if x == 0:
print(f'fact of {x} is 1')
else:
fact = 1
for k in range(2,x+1):
fact *= k
print(f'fact of {x} is {fact}')

Why does this simple Python code break down for large numbers? [duplicate]

This question already has answers here:
Is floating point math broken?
(31 answers)
Closed 2 years ago.
This is a simple code I wrote in Python for telling if the input is odd or even. It is also probably redundant in some parts(I was just trying so that the program doesn't crash for any input).
try:
num = input("Please,\nenter your integer to check if it's odd or even: ")
rem = float(num) % 2
if rem == 0:
print("Your number", int(num), "belongs to the set of even integers!")
elif rem == 1:
print("Your number", int(num), "belongs to the set of odd integers!")
else:
print("Your number", num, "does not belong to the set of integers!")
except ValueError:
print("Your input does not belong to the set of integers!")
Such a simple operation gives a wrong result for a 17 digit number. For example
Please,
enter your integer to check if it's odd or even: 49761934591459137
Your number 49761934591459137 belongs to the set of even integers!
Why is this happening, when python can even perform tetration(repeated exponentiation) of 2 upto 5 times(which is a 19,729 digit number)?
You converted the number to float so this is what happens
number_str = 49761934591459137
print(float(number_str))
>> 4.976193459145914e+16
It gets rounded, if you convert it to integer again you get this
print(int(float(number_str)))
>> 49761934591459136
So the last digit was converted from 7 to 6.
This happens because the float representation in bytes has one part for the exponent and other for the base, which means the least significant digits lose precision on bigger numbers.
You can fix your code by casting the number to integer
rem = int(num) % 2
but a smarter approach would only get the last digit and see if its divisible by 2
rem = int(num[-1]) % 2
So you can write an input of arbitrary length

Change in variable values upon recursion, Python 3

Hey so im pretty new to programming in general and I was having a crack at a question I found for the collatz function,
The code I wrote after some trial and error is as follows:
def collatz(number):
if number % 2 == 0:
number = number//2
print(number)
return number
elif number%2 != 0:
number = 3*number + 1
print(number)
return number
n = int(input("plz enter the number:"))
while n != 1:
n = collatz(n)
Output:
plz enter the number:3
10
5
16
8
4
2
1
This code works but im not sure how the variable values are being alloted, cuz after running this program I can see that in the shell "number = 3" but "n = 1", why is this the case? Shouldnt "number" also equal to 1? Because I am returning the value of number within the function?
Also just to clear my concepts, at the initial moment when I input n = 3, at that moment n = number = 3, then does this returned value of "number" automatically become the new value of n, when i call it in the while loop?
Just wanted to check cuz im a little weak when it comes to doing stuff that needs to pass parameters.
edit:
Why is this case diff then what was just answered?
def testfile(number):
number = number -1
print(number)
return number
n = int(input("enter:"))
while n != 2:
n = testfile(n)
Output:
enter:5
4
3
2
When the input is given as n = 5, then why does number = 3 instead of 5 as was just explained below?
Here's how your program works.
You ask for a number and store it in variable n.
You open a loop which continues until n is 1
Every time the loop repeats, you're calling your function and passing a COPY of n. If you add one to the copy inside the function, your original n will not change.
The COPY is called number. You perform your little tricks with number, output it to the screen, and here's the confusing part: you return a copy of number right back to your loop. And where does it go? It goes right back to n. This overwrites whatever was in n previously.

Error with big number calculations: Why is this happening? [duplicate]

This question already has answers here:
Why does integer division yield a float instead of another integer?
(4 answers)
Closed 3 years ago.
I have created a small Python program in repl.it to illustrate the Collatz Conjecture, which says that if you start with any positive integer number n and you apply the following operations recursively: n/2 if n is even, 3n+1 if n is odd, you will always reach 1.
This is the code:
invalid_input = 0
while(invalid_input == 0):
n = input("Give me a positive integer: ")
try: #check for positive integer. If it cannot do int(n) it means a string was entered, and it goes to except.
if(int(n)>0):
invalid_input = 1 #this is to tell the while loop above that the right input was entered
print("Thank you.")
print("Now loading:")
else: #an integer was entered, but it was negative
print("Please enter a positive integer")
except: #a string was entered
print("Please enter a positive integer")
n=int(n)
nentered = n #this will keep track of the initial n
npeak = n #this will keep track of the highest n reached
iteration = 1 #this will keep track of the number of iterations
iterationmax = 1 #this will keep tack of the iteration at which npeak was reached
while(n != 1):
print("%5i: %5i" % (iteration,n))
if(n % 2 == 0): #divide by 2 if even
n=n/2
else: #if it is odd, multiply by 3 and add 1
n=3*n+1
iteration = iteration + 1
if(n>npeak): #record the higher n and its iteration
npeak = n
iterationmax = iteration
It works. But there is a problem: if the entered number is big enough, for example 6666666666666666666666666, then it does something really strange. This is what I get:
Give me a positive integer: 6666666666666666666666666
Thank you.
Now loading:
1: 6666666666666666666666666
2: 3333333333333333277409280
3: 1666666666666666638704640
4: 833333333333333319352320
5: 416666666666666659676160
6: 208333333333333329838080
7: 104166666666666664919040
8: 52083333333333332459520
9: 26041666666666666229760
10: 13020833333333333114880
etc
As you can see, I am expecting the second number to be exactly 3333333333333333333333333, but instead I am getting different numbers at the end.
As another example, entering 1000000000000000000000000 returns 499999999999999991611392 in the second iteration.
What could be the reason for this?
The reason of why what #ruohola said is true, is because when you use floating-point division with a single /, what happens is that a floating-point number is created. However, it cannot be represented as the number is so large, so it is rounded to the closest most accurate representation. So you will have to use // instead of /.
However, using //, is integer division. This results in an integer which can be represented much easier than a high float.
A very similar question can be found here, it contains some more explanation.
Change your / operation to be //, so that they don't result in (inaccurate) floating point values.
So this:
if(n % 2 == 0): #divide by 2 if even
n=n/2
Should be:
if(n % 2 == 0): #divide by 2 if even
n=n//2
Or as properly formatted by Python conventions:
if n % 2 == 0:
n //= 2

Collatz Sequence - getting a None at the end [duplicate]

This question already has answers here:
Why is "None" printed after my function's output?
(7 answers)
Closed 3 years ago.
Learning from "Automate The Boring Stuff" by Al Sweigart. At the end of Chapter 3, the Collatz Sequence is given as practice. The output seems correct, but the last row has a 'None' in it. In the code below, I am guessing that when p = 1, it gets out of the while loop, and then there is nothing to print, so it gives a None (?). Can someone point me in the right direction of why the None is added, and how to fix it?
See code right below and example results further down:
def collatz (p):
while p != 1:
if p % 2 ==0:
p = (p//2)
print(p)
else:
p = ((3*p) + 1)
print(p)
print ('Select a number between 1 and 10')
entry = float(input())
number = round(entry)
if number >10 or number <1:
print('Your selection must between 1 and 10. Please try again')
else:
Program = collatz(number)
print (Program)
**
Example results:
If I input number as 3, I get:
3
10
5
16
8
4
2
1
None
As was already pointed out in the comments, your function returns None. I thought I'd take your function and make it a generator which you can iterate over and print the values that way. This has several advantages like making your code much more flexible and reusable:
def collatz (p):
while p != 1:
if p % 2 == 0:
p = p / 2 # You don't need the double slash here because of the if before it
else:
p = (3*p) + 1
yield p
print('Select a number between 1 and 10')
number = int(input()) # You really want int here I think and leave out the rounding
if 1 <= number <= 10: # Slightly more pythonic
for sequence_item in collatz(number):
print(sequence_item)
else:
print('Your selection must between 1 and 10. Please try again')
Feel free to ask anything or correct me on possibly wrong assumptions! :)

Categories

Resources