如何跳出这个while循环?

4

我目前在十年级,正在用Python为学校制作一个将二进制数转换为十进制数以及反过来的程序。由于我的编程知识不是很好,因此程序可能不够高效,请您见谅。

以下代码检查用户输入是否只包含1和0,并且不超过8位。当我运行它并输入一个无效的数字时,它可以正常地循环,但当我输入一个有效的数字时,它会一直返回到输入命令,并要求我输入内容,而不是跳出循环并继续下一个操作。请帮忙解决!

max_8bits = 1
only_bin = 1
while max_8bits > 0 or only_bin > 0:

    b2d_num = input("Enter a binary number:")

    for i in range(len(b2d_num)):
        if b2d_num[i] == "0" or b2d_num[i] == "1":
            if i == len(b2d_num):
                only_bin -= 1
        else:
            print("Only enter a binary number! (0's and 1's)")
            break

    if len(b2d_num) > 8:
        print("Only enter up to 8 bits!")
    elif len(b2d_num) <= 8:
        max_8bits -= 1
4个回答

4

i == len(b2d_num) 这个条件永远不可能成立,因为最后一个循环的迭代中 i == len(b2d_num) - 1

例如:

>>> for i in range(10):
       pass

>>> print(i)
9

谢谢!我忘了这个,似乎还有另一个错误,但我已经解决了 :) - tysh444

2
主要问题在于您从未设置退出循环的标志。您永远不会在循环中达到索引8的点,因为循环只执行0-7次。 当您使用break退出for循环时,您没有正确管理值。建议如下:
  1. 使用布尔值而不是整数:这是您头脑中的逻辑。
  2. 简化值检查:使用内置的Python函数。
代码:
too_long = True
not_bin = True

while too_long or not_bin:

    b2d_num = input("Enter a binary number:")

    # Check input length
    too_long = len(b2d_num) > 8
    if too_long:
        print("Only enter up to 8 bits!")
        continue

    # Check input content
    not_bin = False

    for i, bit in enumerate(b2d_num):
        not_bin = not_bin or bit not in "01"

    if not_bin:
        print("Only enter a binary number! (0's and 1's)")

我最终使用了布尔值,但我并不了解一些内置函数,也不理解它们,因此希望避免产生混淆。如果我要使用新的代码片段,我还需要向老师解释,这可能是一个劣势。 - tysh444
我在这里看到的唯一新的内置函数是enumerate;其余的都是标准语言特性。 - Prune

1
条件语句 if i == len(b2d_num): 永远不会被满足,因为 range() 运算符不包括终止值,所以最后一个 i 的值将是 len(b2d_num) - 1
Python语言的目标是易读性强,您可以使用bool代替int来改进代码。下面是一种改进方式:

max_8bits = False
only_bin = False

while not (max_8bits and only_bin):
    b2d_num = input("Enter a binary number:")
    max_8bits = True
    only_bin = True

    # test first condition
    if len(b2d_num) > 8:
        max_8bits = False
        print("Only enter up to 8 bits!")

    # test second condition, but only if first condition is met
    if max_8bits:
        for char in b2d_num:
            if char not in ("0", "1"):
                only_bin = False
                print("Only enter a binary number! (0's and 1's)")
                break

您在评论中提到,您对使用元素迭代而不是使用位置访问的for循环感到犹豫。它们比位置访问要快得多。以下是一个比较:

>>> import timeit

>>> timeit.timeit('for elem in elem_list: _ = elem', 'elem_list = list(range(1000))', number=100000)
0.9983139920514077
>>> timeit.timeit('for i in range(len(elem_list)): _ = elem_list[i]', 'elem_list = list(range(1000))', number=100000)
3.1029140750179067

>>> timeit.timeit('for elem in elem_list: _ = elem', 'elem_list = list(range(10))', number=100000)
0.014086865936405957
>>> timeit.timeit('for i in range(len(elem_list)): _ = elem_list[i]', 'elem_list = list(range(10))', number=100000)
0.06772643199656159

正如您所看到的,使用列表元素的位置访问会导致循环时间大约增加3倍(这可能会有所变化,但是这是一个强烈的指标)。使用for elem in elem_list更易读且更快。

是的,最终我确实进行了更改,谢谢你!不过,我担心我没有使用 for 循环的格式:for char in b2d_num:,所以我很犹豫是否要使用它。 - tysh444
@tysh444 我在关于for循环的答案中添加了一个速度比较。 - Ralf

0

看起来你的代码中,在while循环内有一行 b2d_num = input("Enter a binary number:"),这将导致每次执行while循环时都会运行该代码。

解决方法非常简单,将这段代码放在while循环上面,这样它只会被执行一次。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接