Python算法100例-3.9 勾股数

完整源代码项目地址,关注博主私信'源代码'后可获取

1.问题描述

求100以内的所有勾股数。

所谓勾股数,是指能够构成直角三角形三条边的三个正整数(a,b,c)。

2.问题分析

根据“勾股数”定义,所求三角形三边应满足条件 a 2 + b 2 = c 2 a^2+b^2=c^2 a2+b2=c2。可以在所求范围内利用穷举法找出满足条件的数。

3.算法分析

采用穷举法求解时最容易想到的一种方法是利用三个循环语句分别控制变量a、b、c的取值范围,第一层控制变量a,取值范围是1~100;在a值确定的情况下再确定b值,即第二层控制变量b,为了避免结果有重复现象,b的取值范围是(a+1)~100;a、b的值已确定,利用穷举法在(b+1)~100范围内一个一个地去比较,看当前c值是否满足条件 a 2 + b 2 = c 2 a^2+b^2=c^2 a2+b2=c2,若满足,则输出当前a、b、c的值,否则继续寻找。主要代码如下:

for a in range(1,101):                                  # 确定a的取值
    for b in range(a+1, 101):                       # 确定b的取值
        for c in range(b+1, 101):           # 确定c的取值
            if a*a + b*b == c*c:                    # 判断三个变量是否满足勾股数条件
                print("%4d %4d %4d\t |" %(a, b, c), end="")

但是上述算法的效率比较低,根据 a 2 + b 2 = c 2 a^2+b^2=c^2 a2+b2=c2这一条件,在a、b值确定的情况下没必要再利用循环一个一个去寻找c值。若a、b、c是一组勾股数,则 a 2 + b 2 a^2+b^2 a2+b2的平方根一定等于c,c的平方应该等于a、b的平方和,故可将 a 2 + b 2 a^2+b^2 a2+b2的平方根赋给c,再判断c的平方是否等于 a 2 + b 2 a^2+b^2 a2+b2。根据“勾股数”定义将变量定义为整型, a 2 + b 2 a^2+b^2 a2+b2的平方根不一定为整数,但变量c的类型为整型,将一个实数赋给一个整型变量时可将实数强制转换为整型(舍弃小数点之后的部分),然后再赋值,这种情况下得到的c的平方与原来的 a 2 + b 2 a^2+b^2 a2+b2的值肯定不相等。故可利用这一条件进行判断。

4.完整的程序

%%time
# 勾股数  a**2+b**2=c**2
import math

if __name__ == "__main__":
    count = 0
    print("100以内的勾股数有:")
    # a,b,c分别表示三角形的三条边
    # 满足勾股数的三个数组成的三角形一定是直角三角形
    print("   a\tb\tc   a \t b \tc \t    a \t  b\tc \t    a\t b\tc");
    # 求100以内的勾股数
    for a in range(1,101):
        for b in range(a+1, 101):  # 邻边不能相等,否则就是等边三角形了
            c = int(math.sqrt(a*a + b*b))  # 求c值,并转换为整型
            # 判断c的平方是否等于a*a + b*b ,且两边之和大于第三边
            if c*c == (a*a + b*b) and (a + b > c) and (a + c > b) and (b + c > a) and c <= 100:
                print("%4d %4d %4d\t |" %(a, b, c), end="")
                count += 1
                if count % 4 == 0:
                    print()

100以内的勾股数有:
   a	b	c   a 	 b 	c 	    a 	  b	c 	    a	 b	c
   3    4    5	 |   5   12   13	 |   6    8   10	 |   7   24   25	 |
   8   15   17	 |   9   12   15	 |   9   40   41	 |  10   24   26	 |
  11   60   61	 |  12   16   20	 |  12   35   37	 |  13   84   85	 |
  14   48   50	 |  15   20   25	 |  15   36   39	 |  16   30   34	 |
  16   63   65	 |  18   24   30	 |  18   80   82	 |  20   21   29	 |
  20   48   52	 |  21   28   35	 |  21   72   75	 |  24   32   40	 |
  24   45   51	 |  24   70   74	 |  25   60   65	 |  27   36   45	 |
  28   45   53	 |  28   96  100	 |  30   40   50	 |  30   72   78	 |
  32   60   68	 |  33   44   55	 |  33   56   65	 |  35   84   91	 |
  36   48   60	 |  36   77   85	 |  39   52   65	 |  39   80   89	 |
  40   42   58	 |  40   75   85	 |  42   56   70	 |  45   60   75	 |
  48   55   73	 |  48   64   80	 |  51   68   85	 |  54   72   90	 |
  57   76   95	 |  60   63   87	 |  60   80  100	 |  65   72   97	 |
CPU times: user 6.06 ms, sys: 0 ns, total: 6.06 ms
Wall time: 5.73 ms

5.问题拓展

对于“勾股数”除了利用上面的算法外还有其他方法。

由于任何一个勾股数组(a,b,c)内的三个数同时乘以一个整数n得到的新数组(na,nb,nc)仍然是勾股数,所以一般我们想找的是a、b、c互质的勾股数组。

关于这样的数组,比较常用也比较实用的方法有以下两种。

(1)第一种方法

当a为大于1的奇数2n+1时,b= 2 n 2 + 2 n 2n^2+2n 2n2+2n,c= 2 n 2 + 2 n + 1 2n^2+2n+1 2n2+2n+1

实际上就是把a的平方数拆成两个连续自然数,例如:

·n=1时,(a,b,c)=(3,4,5)

·n=2时,(a,b,c)=(5,12,13)

·n=3时,(a,b,c)=(7,24,25)

……

这是最经典的一个方法,而且由于两个连续自然数必然互质,所以用这个方法得到的勾股数组全部都是互质的。

(2)第二种方法

当a为大于4的偶数2n时,b= n 2 − 1 n^2-1 n21,c= n 2 + 1 n^2+1 n2+1

也就是把a的一半的平方分别减1和加1,例如:

·n=3时,(a,b,c)=(6,8,10)

·n=4时,(a,b,c)=(8,15,17)

·n=5时,(a,b,c)=(10,24,26)

·n=6时,(a,b,c)=(12,35,37)

……

这是次经典的方法,当n为奇数时由于(a,b,c)是三个偶数,所以该勾股数组必然不是互质的;而n为偶数时由于b、c是两个连续奇数必然互质,所以该勾股数组互质。

所以如果只想得到互质的数组,该方法可以改成对于a=4n(n≥2),b= 4 n 2 − 1 4n^2-1 4n21,c= 4 n 2 + 1 4n^2+1 4n2+1,例如:

·n=2时(a,b,c)=(8,15,17)

·n=3时(a,b,c)=(12,35,37)

·n=4时(a,b,c)=(16,63,65)

……

代码如下:

%%time
# 互质勾股数

if __name__ == "__main__":
    a = int(input("请输入一个a值:"))
    print(f'输入a的值为:{a}')
    if a >= 3 and a % 2 == 1:   # 输入的a为奇数,则a = 2n+1, b=2n**2+2n, c=2n**2+2n+1
        n = (a - 1) // 2
        b = 2 * n**2 + 2*n
        c = 2 * n**2 + 2*n + 1
        print("%d %d %d\n" %(a,b,c))
    else:
        if a >= 3 and a % 2 == 0:  # 输入的a为偶数,则a = 2n, b=n**2-1, c=n**2+1
            n = a // 2
            b = n**2 - 1
            c = n**2 + 1
            print("%d %d %d\n" % (a, b, c))
        else:
            print("error")
输入a的值为:101
101 5100 5101

CPU times: user 11.9 ms, sys: 10.7 ms, total: 22.6 ms
Wall time: 2.26 s
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

飘逸高铁侠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值