Python程序设计(第三版)课后题答案 第八章 [约翰·策勒 (著) 人民邮电出版社]

Python程序设计(第三版)课后题答案 第八章

编程练习题

  • 1.斐波那契数列开始是1,1,2,3,4,5,8,……前两个数字之后,序列中的每个数字都是前两个数字之和。编写一个程序,计算并输出第n个斐波那契数,其中n是用户输入的值。
    答案
def main():  # 循环计算斐波那契数列
    n = eval(input('请输入要计算第几位的斐波那契数:'))
    a, b = 1, 1
    i = 1
    while i < n:
        a, b = b, a + b
        i = i + 1
    print('第{0}位的斐波那契数为:{1}'.format(n, a))


main()

输出结果如下:

请输入要计算第几位的斐波那契数:77位的斐波那契数为:13
请输入要计算第几位的斐波那契数:33位的斐波那契数为:2
  • 2.国家气象局使用以下公式计算风寒指数:
    35.74 + 0.6215 T − 35.75 ( V 0.16 ) + 0.4275 T ( V 0.16 ) 35.74 + 0.6215T - 35.75( V^{0.16}) + 0.4275T(V^{0.16}) 35.74+0.6215T35.75(V0.16)+0.4275T(V0.16)
    其中,T是以华氏温度为单位的温度,V是以小时为单位的风速。
    编程打印一张格式漂亮的风寒指数表格。行代表风速为0~50,以5英里/小时为增量,列表示温度从-20 ~ +60,以10为增量。注意:该公式仅适用于每小时超过3英里的风速。

答案

def main():  # 编程打印一张风寒指数表格
    v = 0
    t = -20
    print(' T\V |    ', end='')
    while v <= 50:
        print(v, end='     ')
        v = v + 5
    print('\n-----------------------------------------------------------------------------------')

    while -20 <= t <= 60:
        print(str(t).center(5), end='|')
        v = 0
        while v <= 50:
            if v <= 0:
                print(str('###').rjust(6), end=' ')
            else:
                index = 35.74 + 0.6215 * t - 35.75 * (v ** 0.16) + 0.4275 * t * (v ** 0.16)
                print(str(round(index, 2)).rjust(6), end=' ')
            v = v + 5
        print('\n')
        t = t + 10


main(

输出结果如下:(速度为0时不满足要求,不予计算)

 T\V |    0     5     10     15     20     25     30     35     40     45     50     
-----------------------------------------------------------------------------------
 -20 |   ###  -34.0 -40.72 -45.01 -48.23 -50.83 -53.03 -54.93 -56.62 -58.14 -59.53 

 -10 |   ### -22.26 -28.33 -32.21 -35.11 -37.46 -39.45 -41.17  -42.7 -44.07 -45.32 

  0  |   ### -10.51 -15.93  -19.4  -22.0 -24.09 -25.86  -27.4 -28.77 -29.99 -31.11 

  10 |   ###   1.24  -3.54  -6.59  -8.88 -10.72 -12.28 -13.64 -14.84 -15.92  -16.9 

  20 |   ###  12.98   8.85   6.22   4.24   2.65    1.3   0.13  -0.91  -1.84  -2.69 

  30 |   ###  24.73  21.25  19.03  17.36  16.02  14.88  13.89  13.02  12.23  11.52 

  40 |   ###  36.47  33.64  31.84  30.48  29.39  28.46  27.66  26.95  26.31  25.73 

  50 |   ###  48.22  46.04  44.64   43.6  42.76  42.04  41.43  40.88  40.38  39.93 

  60 |   ###  59.96  58.43  57.45  56.72  56.13  55.63  55.19  54.81  54.46  54.14  
  • 3.用while循环编程,来确定投资在特定利率下翻倍需要多长时间。输入是年利率,输出是投资增加一倍的年数。注:初始投资金额无关紧要,你可以用1元。
    答案
def main():  # 计算投资翻倍的年限
    rate = eval(input('请输入年利率:'))
    pricipal = eval(input('请输入投资金额:'))
    invest = pricipal
    n = 0
    while invest < (2 * pricipal):
        n = n + 1
        invest = pricipal * (1 + n * rate)
    print('第{0}年投资能够增加一倍。'.format(n))


main()

输出结果如下:

请输入年利率:0.03
请输入投资金额:134年投资能够增加一倍。
  • 4.Syracuse(也称“Collatz”或“Hailstone”)序列的生成从一个自然数开始,重复应用以下函数,直到达到1:

s y r ( x ) = {       x / 2 ,    x 为偶数 3 x + 1 ,    x 为奇数 syr(x)= \begin{cases} \ \ \ \ \ x/2, \ \ x为偶数\\ 3x+1,\ \ x为奇数\\ \end{cases} syr(x)={     x/2,  x为偶数3x+1,  x为奇数
       例如,从5开始的Syracuse序列是5,16,8,4,2,1。数学中有一个悬而未决的问题:对于每个可能的起始值,该序列是否总会到达1。
       编程从用户获取起始值,然后打印该起始值的Syracuse序列。
答案

def main():  # Syracuse序列
    initial = eval(input('请输入初始值(大于0):'))
    print('{0}的Syracuse序列是:{0}'.format(initial), end=' ')
    while initial != 1:
        while judge_odd_number(initial):
            initial = 3 * initial + 1
            print(initial, end=' ')
        while judge_even_number(initial):
            initial = int(initial / 2)
            print(initial, end=' ')


main()

输出结果如下:

请输入初始值(大于0):5
5的Syracuse序列是:5 16 8 4 2 1 
请输入初始值(大于0):15
15的Syracuse序列是:15 46 23 70 35 106 53 160 80 40 20 10 5 16 8 4 2 1 
  • 5.正整数n>2是素数,如果2和n(不含n)之间的数字都不能整除n。编程接受n值作为输入,并确定该值是否为素数。如果n不是素数,那么程序应该在发现能整除n的值后立即退出。
    答案
def main():  # 判断素数
    n = eval(input('请输入要判断的数(n>2):'))
    for i in range(2, n):
        if n % i == 0:
            print('{0}不是素数'.format(n))
            break
        elif i + 1 == n:
            print('{0}是素数'.format(n))


main()

输出结果如下:

请输入要判断的数(n>2)4
4不是素数
请输入要判断的数(n>2)7
7是素数
请输入要判断的数(n>2)9
9不是素数
  • 6.修改上一个程序,找出小于或等于n的每个素数。
    答案
def judge_prime_number(n):  # 判断素数
    # n = eval(input('请输入要判断的数(n>2):'))
    for i in range(2, n):
        if n % i == 0:
            return False
            # print('{0}不是素数'.format(n))
            # break
        elif i + 1 == n:
            return True
            # print('{0}是素数'.format(n))


def main():  # 找出<=n的素数
    n = eval(input('请输入要找的数(n>2):'))
    for i in range(n+1):
        if judge_prime_number(i):
            print(i, end=' ')


main()

输出结果如下:

请输入要找的数(n>2)17
3 5 7 11 13 17 
请输入要找的数(n>2)101
3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 101 
  • 7.哥德巴赫猜想认为每个偶数都是两个素数之和。编程从用户那里获取一个数字,检查以确保它是偶数,然后找到两个素数,和为该数字。
    答案:
def main():  # 2个素数之和为偶数,找这两个素数
    n = eval(input('请输入一个数:'))
    if judge_even_number(n) and n > 2:
        p = [1]
        for i in range(n + 1):
            if judge_prime_number(i):
                p = p + [i]
        q = []
        for i in range(len(p)):
            for j in range(len(p)):
                if p[i] + p[j] == n:
                    q = q + [(p[i], p[j])]
        if judge_even_number(len(q)):
            print('可能得素数组合有:', q[0:int(len(q) / 2)])
        else:
            print('可能得素数组合有:', q[0:(int(len(q)/2) + 1)])
    else:
        print('输入的数不符合要求!')


main()

输出结果如下:

请输入一个数:8
可能得素数组合有: [(1, 7), (3, 5)]
请输入一个数:7
输入的数不符合要求!
请输入一个数:100
可能得素数组合有: [(3, 97), (11, 89), (17, 83), (29, 71), (41, 59), (47, 53)]
  • 8.可以用欧几里得的算法计算两个值的最大公约数(GCD)。从值m和n开始,我们反复应用公式:n,m = m,n%m,直到m为0。这时,n就是原始m和n的GCD。用这个算法编程求两个数字的GCD。
    答案:
def main():  # 计算最大公约数
    m, n = eval(input('请输入两个数:'))
    while m != 0:
        n, m = m, n % m
    print('这两个数的最大公约数是:', n)


main()

输出结果如下:

请输入两个数:24,96
这两个数的最大公约数是: 24
请输入两个数:63,91
这两个数的最大公约数是: 7
  • 9.编程计算多段旅游的燃油效率。该程序会首先提示输入开始时里程表的读数,然后获取有关一系列分段旅程的信息。对于每个分段,用户输入当前的里程表读数和使用的汽油量(用空格分隔)。用户用空白行来表示行程结束。该程序打印出每段旅程上每加仑的英里数以及旅程的总MPG(英里/加仑)。
    答案:
def main():  # 计算旅程,英里/加仑
    initial_odometer = eval(input('请输入当前里程表的读数:'))
    str = input('请输入当前分段旅程的里程表读数和使用汽油量:')
    tmile, tgasoline = 0, 0
    while str != '':
        current_odometer = float(str.split(' ')[0])
        gasoline = float(str.split(' ')[1])
        mile = current_odometer - initial_odometer
        mile_gasoline = mile / gasoline
        tmile = tmile + mile
        tgasoline = tgasoline + gasoline
        mpg = tmile / tgasoline
        print('本段里程的每加仑的英里数为:{0:0.2f},总的MPG为:{1:0.2f}。'.format(mile_gasoline, mpg))
        str = input('请输入当前分段旅程的里程表读数和使用汽油量:')


main()

输出结果如下:

请输入当前里程表的读数:0
请输入当前分段旅程的里程表读数和使用汽油量:50 10
本段里程的每加仑的英里数为:5.00,总的MPG为:5.00。
请输入当前分段旅程的里程表读数和使用汽油量:100 20
本段里程的每加仑的英里数为:5.00,总的MPG为:5.00。
请输入当前分段旅程的里程表读数和使用汽油量:150 40
本段里程的每加仑的英里数为:3.75,总的MPG为:4.29。
请输入当前分段旅程的里程表读数和使用汽油量:200 45
本段里程的每加仑的英里数为:4.44,总的MPG为:4.35。
请输入当前分段旅程的里程表读数和使用汽油量:

进程已结束,退出代码0
  • 10.修改上一个程序,从文件获取输入。
    答案:
def main():  # 计算旅程,英里/加仑
    fileName = input("What file are the numbers in? ")
    infile = open(fileName, 'r')
    initial_odometer = int(infile.readline())
    str = infile.readline()
    tmile, tgasoline = 0, 0
    while str != '':
        current_odometer = float(str.split(' ')[0])
        gasoline = float(str.split(' ')[1])
        mile = current_odometer - initial_odometer
        mile_gasoline = mile / gasoline
        tmile = tmile + mile
        tgasoline = tgasoline + gasoline
        mpg = tmile / tgasoline
        print('本段里程的每加仑的英里数为:{0:0.2f},总的MPG为:{1:0.2f}。'.format(mile_gasoline, mpg))
        str = infile.readline()


main()

输入文件内容如下:
在这里插入图片描述
输出结果如下:

What file are the numbers in? mile.txt
本段里程的每加仑的英里数为:5.00,总的MPG为:5.00。
本段里程的每加仑的英里数为:4.50,总的MPG为:4.78。
本段里程的每加仑的英里数为:2.51,总的MPG为:3.28。
本段里程的每加仑的英里数为:4.17,总的MPG为:3.56。

进程已结束,退出代码0
  • 11.加热和制冷的“度天”是公用事业公司估计在此处键入公式。能源需求的测量指标。如果某天的平均温度低于60摄氏度,则在加热度天数中加入低于60摄氏度的度数。如果温度高于80摄氏度,则在制冷度天数中加入超过80摄氏度的度数。编程接受每日平均温度的序列,并计算制冷和加热度天数的不断增长的总和,所有的数据处理完成后,程序应该打印这两个总和。
    答案:
def main():
    refrigeration = 0
    heating = 0
    str = input('请输入每日平均温度的序列:')
    while str != '':
        list = str.split(' ')
        for i in range(len(list)):
            if float(list[i]) < 60:
                refrigeration = refrigeration + (60 - float(list[i]))
            elif float(list[i]) > 80:
                heating = heating + (float(list[i]) - 80)
        print('制冷度天数的总和为:{0:0.2f},制热度天数的总和为:{1:0.2f}。'.format(refrigeration, heating))
        break


main()

输出如下:

请输入每日平均温度的序列:58 82 99 102 55 15 78 99 130
制冷度天数的总和为:52.00,制热度天数的总和为:112.00。

进程已结束,退出代码0
  • 12.修改上一个程序,从文件获取输入。
    答案:
def main():
    refrigeration = 0
    heating = 0
    fileName = input("What file are the temperature in? ")
    infile = open(fileName, 'r')
    str = infile.readline()
    while str != '':
        list = str.split(' ')
        for i in range(len(list)):
            if float(list[i]) < 60:
                refrigeration = refrigeration + (60 - float(list[i]))
            elif float(list[i]) > 80:
                heating = heating + (float(list[i]) - 80)
        str = infile.readline()
    print('制冷度天数的总和为:{0:0.2f},制热度天数的总和为:{1:0.2f}。'.format(refrigeration, heating))


main()

输入文件内容如图:
在这里插入图片描述
输出结果如下:

What file are the temperature in? temperature.txt
制冷度天数的总和为:188.00,制热度天数的总和为:187.00
  • 13.编写一个程序,以图形方式绘制回归线,即通过一个点集的最佳曲线。首先要求用户在图形窗口中点击,指定数据点。为了表示输入结束,将一个标有“Done”的小矩形放在窗口的左下角。当用户在该矩形内点击时,程序将停止收集数据点。
           回归线是满足以下公式的线:
    y = y ˉ + m ( x − x ˉ ) y= \bar{y} +m(x- \bar{x}) y=yˉ+m(xxˉ)
    其中
    m = ∑ x i y i − n x ˉ y ˉ ∑ x i 2 − n x ˉ 2 m = \frac {\sum x_iy_i - n\bar{x}\bar{y} }{\sum x_i^2 - n\bar{x}^2} m=xi2nxˉ2xiyinxˉyˉ
    x ˉ \bar{x} xˉ x x x的平均值, y ˉ \bar{y} yˉ y y y的平均值, n n n是点数。
    当用户点击数据点时,程序应将它绘制在图形窗口中,并记录输入值的计数,以及x,y, x 2 x^2 x2和xy值的不断增长的总和。当用户单击“Done”矩形内部时,程序随后计算窗口左边缘和右边缘的x值对应的y值(用上面的公式),以计算穿越窗口的回归线的端点。线绘制后,程序将暂停并待另一次鼠标点击,然后关闭窗口并退出。
    答案:
def main():  # 计算线性回归线
    win = GraphWin('回归线', 800, 600)
    win.setBackground('white')
    win.setCoords(0, 0, 100, 100)

    r = Rectangle(Point(80, 15), Point(90, 20))    # 绘制灰色提示框
    r.setFill('gray')
    r.draw(win)

    t = Text(Point(85, 17.5), 'Done')    # 绘制提示词“Done”
    t.setFill('black')
    t.draw(win)

    n, xm, ym, xym, xs = 0, 0, 0, 0, 0
    xl, xr = 100, 0
    while True:
        pt = win.checkMouse()
        if pt and 80 < pt.getX() < 90 and 15 < pt.getY() < 20:  # 判断有点且点的位置是否在“Done”区域内
            break
        elif pt:
            n = n + 1
            pt.draw(win)
            x = pt.getX()
            y = pt.getY()
            if x < xl:  # 记录点的x坐标的最小值
                xl = x
            if x > xr:  # 记录点的x坐标的最大值
                xr = x
            xy = x * y  # 点坐标的乘积
            xm = xm + x  # 点X坐标的求和
            ym = ym + y  # 点Y坐标的求和
            xym = xym + xy  # 点X,Y坐标的乘积的求和
            xs = xs + x ** 2  # 点X坐标的平方的求和
    m = (xym - n * (xm / n) * (ym / n)) / (xs - n * ((xm / n) ** 2))  # 根据给定公式计算m值
    yl = (ym / n) + m * (xl - (xm / n))   # 根据给定公式计算线段左端点的y值
    yr = (ym / n) + m * (xr - (xm / n))   # 根据给定公式计算线段右端点的y值
    line = Polygon(Point(xl, yl), Point(xr, yr))
    line.draw(win)

    win.getMouse()
    win.close()


main()

输出结果如下:
在这里插入图片描述

  • 14.编写一个将色彩图像转换为灰度的程序。用户提供包含GIF和PPM图像文件的名称,程序加载图像并显示文件。再单击鼠标时,程序将图像转换为灰度。然后提示用户输入文件名,保存灰度图像。
    你可能要回去复习一下graphics库中的Image对象。转换图像的基本思想是遍历它的每个像素,将颜色转换为合适的灰度。设置红绿蓝的比值,让他具有相同的亮度,从二创创建灰色像素。所以color_rgb(0,0,0)是黑色,color_rgb(255,255,255)是白色,color_rgb(127,127,127)是50度灰。你应该使用原始RGB值的加权平均值来确定灰度的亮度。下面是灰度算法的伪代码:
for each row in the image:
    for each column in the image:
        r, g, b = get piexl information for current row and column 
        brightness = int ( round (0.299r + 0.587g + 0.114b)
          set pixel to color_rgb(brightness, brightness, brightness)
    update the image  # to see progess row by row

注意:Image类中的像素操作相当慢,因此要使用较小的图像(不是1200万像素)来测试你的程序。

答案:

def main():  # 图像变灰

    win = GraphWin('灰度图像', 400, 300)
    win.setBackground('white')
    win.setCoords(0, 0, 100, 100)
    win.getMouse()

    fileName = input("What file is the picture? ")
    picture = Image(Point(50, 50), fileName)
    picture.draw(win)
    win.getMouse()

    pw = picture.getWidth()
    ph = picture.getHeight()

    for i in range(0, pw):
        for j in range(0, ph):
            r, g, b =picture.getPixel(i, j)
            brightness = int(round(0.299*r + 0.587*g + 0.114*b))
            picture.setPixel(i, j, color_rgb(brightness, brightness, brightness))
    NewfileName = input("Enter a name to save the new file:")
    picture.save(NewfileName)

    win.getMouse()
    win.close()


main()

输出过程如下:首先在窗口中显示彩色人物照片,
在这里插入图片描述
更改像素变为灰色:
在这里插入图片描述
运行交互时输入要打开的图像名称和要保存的文件名称:

What file is the picture? xiaoyan.png
Enter a name to save the new file:xiaoyan2.png

进程已结束,退出代码0
  • 15.编写程序将图像转换成其他补色。程序的一般形式将于上一个问题类似。通过从255减去每个颜色值来得到像素的补值。因此,新像素的颜色是color_rgb(255-r,255-g,255-b)。
    答案:
def main():  # 图像变为补色像素展示

    win = GraphWin('灰度图像', 400, 300)
    win.setBackground('white')
    win.setCoords(0, 0, 100, 100)
    win.getMouse()

    fileName = input("What file is the picture? ")
    picture = Image(Point(50, 50), fileName)
    picture.draw(win)
    win.getMouse()

    pw = picture.getWidth()
    ph = picture.getHeight()

    for i in range(0, pw):
        for j in range(0, ph):
            r, g, b = picture.getPixel(i, j)
            picture.setPixel(i, j, color_rgb(255 - r, 255 - g, 255 - b))
    NewfileName = input("Enter a name to save the new file:")
    picture.save(NewfileName)

    win.getMouse()
    win.close()


main()

输出过程如下:首先在窗口中显示彩色人物照片,
在这里插入图片描述
更改像素变为原像素的补值后图像如图所示:
在这里插入图片描述
运行交互时输入要打开的图像名称和要保存的文件名称:

What file is the picture? xiaoyan.png
Enter a name to save the new file:xiaoyan3.png

进程已结束,退出代码0
  • 16.修改event_loop3程序,以使用书中所述的键。用户在Entry框中输入时,按键应该导致消失,并丢弃在框中输入的所有文本。
    答案:
def handleKey(k, win):
    if k == "r":
        win.setBackground("pink")
    elif k == "w":
        win.setBackground("white")
    elif k == "g":
        win.setBackground("lightgray")
    elif k == "b":
        win.setBackground("lightblue")


def handleClick(pt, win):
    entry = Entry(pt, 10)
    entry.draw(win)

    while True:
        key = win.getKey()
        if key == "Return":
            entry.undraw()
            Text(pt, entry.getText()).draw(win)
            break
        if key == "Escape":  # loop exit
            entry.undraw()
            break
    
    win.checkMouse()


def main():
    win = GraphWin("Click and Type", 500, 500)

    while True:
        key = win.checkKey()
        if key == "q":  
            break

        if key:
            handleKey(key, win)

        pt = win.checkMouse()
        if pt:
            handleClick(pt, win)

    win.close()


main()

输出窗口中:按下Esc键,Entry框消失,文本丢失;按下Enter键,Entry框消失,文本显示在图像中。
在这里插入图片描述







(如有错误,请读者批评指正!)
  • 27
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值