简体   繁体   English

Python while 循环无法按预期工作

[英]Python while loop not working as intended

I don't know how to get over this problem with while loop.我不知道如何用 while 循环解决这个问题。 So basically I want to return the number of zeros at the end of a number's factorial.所以基本上我想在一个数字的阶乘末尾返回零的数量。

import math


def zeros(n):
    total_zero = 0
    n = math.factorial(n)
    while str(n)[-1] == '0':  # to check if the last number is 0 or not
        n = n * 0.1
        total_zero += 1

    return total_zero


output = zeros(30)
print(output)

After the while loop runs only 1 time, it breaks; while 循环只运行了 1 次后就中断了; I don't know why.我不知道为什么。

Help would be very appreciated.帮助将不胜感激。 Thanks!谢谢!

After multiplying your value by 0.1 it becomes a float , and it's string representation becomes the scientific notation 2.6525285981219107e+31 which doesn't end by a 1将您的值乘以0.1它变成一个float ,它的字符串表示变成科学记数法2.6525285981219107e+31 ,它不以1结尾

You'd better do the integer division by 10 to keep an int你最好将整数除以 10 以保持一个int

def zeros(n):
    total_zero = 0
    n = math.factorial(n)
    while str(n)[-1] == '0':  # to check if the last number is 0 or not
        n = n // 10
        total_zero += 1
        print(f"testting {str(n)}")
    return total_zero

>> zeros(30)
testting 26525285981219105863630848000000
testting 2652528598121910586363084800000
testting 265252859812191058636308480000
testting 26525285981219105863630848000
testting 2652528598121910586363084800
testting 265252859812191058636308480
testting 26525285981219105863630848
7

Better You can also use str.rstrip : you remove the leading zeros and check the length difference更好您还可以使用str.rstrip :您删除前导零并检查长度差异

def zeros(n):
    value = str(math.factorial(n))
    return len(value) - len(value.rstrip("0"))

My first answer above was literally solving the question that the user asked: "Why doesn't my code work?"我上面的第一个答案是从字面上解决用户提出的问题:“为什么我的代码不起作用?” But there is a much much simpler way of solving the question "How many zeros does n! have at the end" which is so simple you can do the math in your head.但是有一种更简单的方法可以解决“n 有多少个零!最后”这个问题,它非常简单,您可以在脑海中进行数学计算。

Look at the prime factorization of any number f .看看任意数f的质因数分解。 To get a "0" at the end of a number, you must have 2 x 5 in the prime factorization.要在数字末尾得到“0”,质因数分解中必须有 2 x 5。 So the number of zeros at the end of f is just the minimum of the number of 2s and the number of 5s in the prime factorization.所以 f 末尾的零的数量只是质因数分解中 2 的数量和 5 的数量中的最小值。 For factorials, you always get more factors of 2 than of 5, so we're down to the question: How many 5s are there in the prime factorization of n!对于阶乘,2 的因数总是多于 5 的因数,所以我们的问题是:n 的质因数分解中有多少个 5!

That's easy!这很容易! Legendre's formula says it is: floor(n/5) + floor(n/25) + floor(n/125) + ... and although this is an infinite series, after a couple of terms, they're all zero.勒让德的公式说它是: floor(n/5) + floor(n/25) + floor(n/125) + ...虽然这是一个无限级数,但经过几项后,它们都为零。 For 30!, you get 6 + 1 + 0 + 0 + ... = 7 .对于 30!,你得到6 + 1 + 0 + 0 + ... = 7

If asked how many 0s there are at the end of 1000!, the answer is `200 + 40 + 8 + 1 = 249'如果问 1000! 的末尾有多少个 0,答案是“200 + 40 + 8 + 1 = 249”

Why didn't you bother to do any debugging?你为什么不费心做任何调试? See thislovely debugging site for help.请参阅这个可爱的调试站点以获取帮助。 A simple print to trace n shows the problem.跟踪n简单print显示了问题。

You're doing a float computation on an integer;您正在对整数进行float计算; the result you get back is not guaranteed to be exact. 不能保证您返回的结果是准确的。 Instead, use相反,使用

n = n // 10

After you multiply by .1, you have a floating point number.乘以 0.1 后,您将得到一个浮点数。 You will be losing precision with a number as large as 30!使用大到 30 的数字将失去精度! You want to divide by 10 using //.您想使用 // 除以 10。

Also rather than looking at the last digit in the string, you can just look at the number mod 10. Much faster此外,您无需查看字符串中的最后一位数字,而只需查看数字 mod 10。速度要快得多

In python, the * operator on an int and float outputs a float .在 python 中, intfloat上的*运算符输出一个float Casting to str converts long floats into scientific notation.转换为str会将长浮点数转换为科学记数法。 Therefore on your second iteration you have:因此,在您的第二次迭代中,您有:

> str(math.factorial(30)*.1)
'2.6525285981219107e+31'
> str(math.factorial(30)*.1)[-1]
'1'

Since math.factorial always returns an int , which str converts to a string of the full integer value, you might try first converting the output of math.factorial to a string, and then iterating backward through that string.由于math.factorial总是返回一个int ,它str转换为完整整数值的字符串,您可以尝试首先将math.factorial的输出转换为字符串,然后通过该字符串向后迭代。 Something like:就像是:

def count_zeros(n):
    count = 0
    n = str(math.factorial(n))
    while n[-1] == '0':
        count += 1
        n = n[:-1]
    return count

This could be solved a bit more compactly as follows这可以更紧凑地解决如下

from math import factorial
from itertools import takewhile

def zeros(n):
    return sum(1 for _ in takewhile(lambda i: i == '0', reversed(str(factorial(n)))))

For example例如

>>> zeros(30)
7

This basically computes the factorial, converts that to a string, then counts the '0' characters from the string backwards until it encounters a non-zero character.这基本上计算阶乘,将其转换为字符串,然后从字符串向后计算'0'字符,直到遇到非零字符。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM