背景介绍

使用过python的小伙伴都知道,很多时候需要使用input()函数来提取用户键盘输入并进行边界判断,今天博主遇到一个用户输入判断的问题,在问CS小伙伴的时候突然想到了可以用递归解决,下面就及时分享一下。

涉及到的问题很简单:

编写程序,提示输入大于2的整数(检查),然后反复求该数字的平方根直到小于2,显示每次得到的平方根与已经完成的操作次数,输出时采用3位小数的格式。

代码逻辑很简单,但是在判断用户输入的时候遇到了问题。

问题描述

按照套路,我们应该使用while...end...语句,其中end语句在while判断为false的时候执行,我们的函数使用的是raw_input, 'integer'.isdigit()和int()函数,分别进行字符串输入,整数字符串判断和整数类型转换。

不多说,先上最开始的代码:

input_num = raw_input("Please enter a number larger than 2: ")
while not input_num.isdigit():
    input_num = raw_input("Incorrect, should be a number, enter again: ")
else:
    input_num = int(input_num)
    while input_num <= 2:
        input_num = raw_input("Incorrect, should be a number larger than 2, enter again:")
    else:
        input_num = int(input_num)

看起来跟粗犷,这里有一个逻辑bug,如果用户第一次输入 0,第二次输入 "wtf" ,那么程序会因为int()函数不接受非整数字符串而报错;但是我们必须先判断是否input为整数字符串再使用int(即不能用and同时判断俩),所以这里出现了一个问题,大家可以先思考一下问题的本质是什么?

问题解答

看标题我们已经知道要通过递归解决这个问题了,熟悉递归的同学应该知道典型的例子就是factorial和fibonacci,在这里我们也可以使用递归函数去解决这个input判断的问题。

问题本质
这个问题的本质在于,如果第二个while循环是true(即输入不符合大于2的要求),那么我们需要重新回到第一个while循环开始判断,而python自带的break并不能从while...end...里头的嵌套跳回到顶部,所以这里需要重新调用顶层while循环。

知道了这点,接下来就非常好做了,直接贴上整个小程序供大家参考。同时可以学习一下目前推荐使用的.format的输出格式({元组中的位置:占n个位置d表示整数}.format(对象))

 
import math
 
def checkinput():
    input_num = raw_input("Please enter a number larger than 2: ")
    while not input_num.isdigit():
        input_num = raw_input("Incorrect, should be a number, enter again: ")
    else:
        input_num = int(input_num)
        while input_num <= 2:
            input_num = checkinput()
    return input_num
 
input_num = checkinput()
 
num = input_num
counter = 0
print("{0:2d}: {1:.3f}" .format(counter, num))
while num > 2:
    num = math.sqrt(num)
    counter += 1
    print("{0:2d}: {1:.3f}" .format(counter, num))

运行结果

# Please enter a number larger than 2: 1
# Please enter a number larger than 2: wtf
# Incorrect, should be a number, enter again: 233
#  0: 233.000
#  1: 15.264
#  2: 3.907
#  3: 1.977