小熊奶糖(BearCandy)
小熊奶糖(BearCandy)
发布于 2024-05-14 / 12 阅读
0
0

Python 自定义函数综合实训

1.编写函数,判断用户数入的3个数字是否为回文数。回文数是一个正向和逆向都相同的整数,如123454321,9889

错误写法:

def huiwen(string):
  count=len(string)
  center=(count-1)/2 #索引
  print(int(center))
  center1=-(count/2)
  list_one=list(string) #转化为列表
  list_two=  
  list_three=    
  for i in list_one :center :
    list_two.append(i)
  for i in list_one -1:center1 :
    list_three.append(i)
  if list_two == list_three:
    print('是回文数')

这段代码的目的是检查一个字符串是否是回文,即正着读和反着读都一样的字符串。但是,这段代码中存在一些问题,导致了错误。我将逐一解释这些问题,并提供一个修正后的版本。

  1. 计算中心索引:
    • center=(count-1)/2 这行代码计算的是字符串中心的索引,但是当字符串长度为奇数时,中心是一个字符,而不是两个字符之间的空隙。因此,这里不需要减1。
    • center1=-(count/2) 这行代码试图计算负的索引,但是Python不支持负的索引直接用在切片操作中。
  2. 列表推导式:
    • for i in list_one[:center]:for i in list_one[-1:center1]: 这两个循环试图分别创建前半部分和后半部分的列表,但是使用了错误的索引。
  3. 比较列表:
    • 即使上面的问题被修正,if list_two == list_three: 这行代码也不能正确判断字符串是否为回文,因为列表 list_twolist_three的顺序是相反的。
      下面是一个修正后的代码版本,这段代码将正确地检查一个字符串是否是回文:
def huiwen(string):
    count = len(string)
    center = count // 2  # 计算中心索引
    # 分别获取前半部分和后半部分的字符串
    front = string[:center]
    back = string[-center:]
    # 比较前半部分和反转的后半部分
    if front == back[::-1]:  # 使用[::-1]来反转字符串
        print('是回文数')
    else:
        print('不是回文数')
# 测试函数
huiwen("上海自来水来自海上")  # 应该输出 '是回文数'
def huiwen(string):
    # 直接获取字符串长度
    count = len(string)
  
    # 根据字符串长度的奇偶性决定中心索引或索引对
    if count % 2 == 0:  # 偶数长度
        center1 = count // 2 - 1
        center2 = count // 2
    else:  # 奇数长度
        center1 = center2 = count // 2
  
    # 切片直接比较前半部分和翻转后的后半部分
    first_half = string[:center2]
    second_half = string[center1+1:][::-1]  # 注意这里切片后反转以获得正确的后半部分
  
    # 比较两部分是否相等
    if first_half == second_half:
        print('是回文字符串')
    else:
        print('不是回文字符串')

# 测试函数
huiwen("level")  # 应输出:是回文字符串
huiwen("hello")  # 应输出:不是回文字符串

这段代码首先计算字符串的中心索引,然后分别获取前半部分和后半部分的字符串。最后,通过比较前半部分和反转后的后半部分来确定字符串是否为回文。

second_half = string[center1+1:][::-1]

这段代码的目的是为了获取原字符串的后半部分,并将其反转,以便与前半部分进行比较以判断是否为回文。这里是分步解析:

  1. string[center1+1:]

    • center1 是根据字符串长度和奇偶性计算得到的一个索引位置。如果字符串长度是奇数,center1 就是中间索引;如果是偶数,它会是中间偏左的索引。
    • center1 + 1 的目的是确保我们从中心点的下一个字符开始截取(对于奇数长度字符串,这是为了避免重复选取中间字符;对于偶数长度,则是从右半部分的实际开始处截取)。
    • string[center1+1:] 表示从 center1+1 这个位置直到字符串结束的所有字符。
  2. [::-1]

    • 这是Python中的切片语法,用于序列的反向切片。
    • 当应用于字符串时,[::-1] 表示从字符串的末尾开始取到字符串的开头,步长为-1,即反向取出所有字符,实现字符串的反转。

综上,second_half = string[center1+1:][::-1] 先根据字符串的中心位置切取出后半部分,然后将这部分字符串反转,这样就可以和前半部分进行比较,以验证整个字符串是否为回文。简而言之, 进行了两次切片,第一次切片从中间值开始,第二次切片反向切片。Python不支持直接反向切片索引。

编写函数,输出1~100中偶数之和

def count_num():
  count=0
  for i in range(1,101):
    if i%2==0:
      count+=i
    print(count)

2.编写函数,计算20x19x18x···x3的结果

用到了递归函数(函数内部调用了自身)

def func(num):
  if num==1:
    return 1
  else:
    return num*func(num-1)

不可使用break,continue因为其不是循环

3.编写函数,判断用户数入的3个数字是否能构成是三角形的三边

def sanjiao(*args):
  if args[0] + args[1]>args[2]:
    if args[0] + args[2]>args[1]:
      if args[1] + args[2] > args[0]:
        print ('是三角形')
      else:
        print('不是三角形')
    else:
        print('不是三角形')
  else:
    print('不是三角形')

4.编写函数,求2个正整数的最小公倍数

错误写法:

def minbeen(a,b=0):
  for  i in range(2,a+1):
    for y in range(2,a+1):
      if i*y==a:
        print(f'{i}和{y}是{a}的最小公倍数')
  if not(b==0):
    return minbeen(b)

这段代码的目的是求最小公倍数,但是实现的方式是错误的。首先,这段代码实际上是找出能够相乘得到 a的两个数,而不是求 a的最小公倍数。其次,这段代码没有处理当 b不为0的情况,即求两个数的最小公倍数。
最小公倍数(Least Common Multiple, LCM)是能被两个或多个整数共同整除的最小正整数。求两个数的最小公倍数通常需要先求出它们的最大公约数(Greatest Common Divisor, GCD),然后使用以下公式计算:

\text{LCM}(a, b) = \frac{|a \times b|}{\text{GCD}(a, b)}

下面是一个修正后的代码版本,这段代码将正确地求出两个数的最小公倍数:

def gcd(a, b):
    """求最大公约数"""
    while b:
        a, b = b, a % b
    return a
def lcm(a, b):
    """求最小公倍数"""
    return abs(a * b) // gcd(a, b)
# 测试函数
print(lcm(12, 18))  # 应该输出 36,因为12和18的最小公倍数是36

这段代码首先定义了一个求最大公约数的函数 gcd,然后定义了一个求最小公倍数的函数 lcm。在 lcm函数中,使用了前面提到的公式来计算最小公倍数。

在Python中,a, b = b, a % b 是一种常见的赋值操作,它同时更新了两个变量的值。这种操作通常用于算法中,特别是在计算最大公约数(GCD)的欧几里得算法中。
让我们逐步解释这个操作:

  1. a % b 是取a除以b的余数。
  2. b, a % b 是一个元组,创建了一个包含两个元素的临时元组 (b, a % b)
  3. a, b = b, a % b 是一个解包赋值操作,它将元组 (b, a % b) 中的值分别赋给 ab
    具体步骤如下:
  • a 被赋值为 b,即 a 变成了 b 的当前值。
  • b 被赋值为 a % b,即 b 变成了 a(在赋值之前的原始值)除以 b(在赋值之前的原始值)的余数。
    这个操作是欧几里得算法的关键步骤,它基于这样一个事实:两个整数的最大公约数与它们的差的最大公约数相同。因此,通过不断将较大数替换为两数之差,我们可以逐渐缩小问题的规模,直到其中一个数变为0。此时,另一个数就是原始两数的最大公约数。
    例如,如果我们用这个算法来计算 gcd(48, 18)
  1. 初始值:a = 48, b = 18
  2. 第一次迭代:a = 18, b = 48 % 18 = 12
  3. 第二次迭代:a = 12, b = 18 % 12 = 6
  4. 第三次迭代:a = 6, b = 12 % 6 = 0
    b 变为0时,算法结束,a 的值就是两数的最大公约数,即 gcd(48, 18) = 6

5.兔子数列

错误写法:

#兔子数列
def countrabbit(num,month=1,num1=0):
  if month<12:
    if not(month<=2):
      a=num+num
      month+=1
      return countrabbit(a,month,num)
    else:
      month+=1
      a=num+num
      return countrabbit(a,month)
  else:
    return num
  
print (countrabbit(2))

这个程序的目的是计算兔子数列(斐波那契数列的一个变种)在给定月份的数量,但存在一些逻辑错误和语法错误。以下是修正后的代码及对错误的详细说明:

修正后的代码

def count_rabbits(month=1, num=1, num_prev=0):
    if month > 12:
        return num
    else:
        # 第一个月和第二个月都是初始化值,从第三个月开始计算
        if month <= 2:
            num_next = num
        else:
            # 每月的兔子数量是前两个月数量之和
            num_next = num + num_prev
  
        # 递归调用,更新月份、当前月兔子数量和上个月兔子数量
        return count_rabbits(month + 1, num_next, num)

print(count_rabbits(1))

错误说明

  1. 参数顺序和命名:原始函数参数顺序和命名不够直观。修正后将参数顺序调整为 monthnum(当前月数量)、num_prev(上个月数量),并更清晰地命名函数为 count_rabbits
  2. 逻辑错误:原始代码中判断 if not(month<=2):是为了从第三个月开始计算新兔子数量,但逻辑表达不恰当且导致了不必要的复杂性。修正后的代码通过简化条件直接计算每个月的兔子总数。
  3. 递归返回值:原始代码在递归调用时,没有正确传递所有必要的状态信息到下一次调用。修正后的代码确保每次递归调用都更新了 numnum_prev,以正确累计兔子数量。
  4. 基础案例处理:原始代码对于 month<12的情况处理不当,修正后的代码通过检查 month > 12作为递归终止条件,更清晰地表达了当超过12个月时返回最终的兔子数量。
  5. 初始调用:考虑到兔子数列的计算特性,修正后的示例调用设置 month=1作为默认值,并明确指定第一个月的兔子数量为1(而非2,因为通常斐波那契序列或类似兔子繁殖问题从0或1开始计算,这里假设初始为一对兔子)。

通过上述修改,代码现在能正确地计算并输出给定月份内兔子的预期数量。

兔子数列(通常称为斐波那契数列的一个变体)的基本假设是在理想状态下,从第3个月开始,每个月的兔子对数是前两个月的兔子对数之和。但这里的实现试图通过额外的参数和条件来控制流程,导致逻辑不够清晰。

下面是修正后的版本,以更简洁和准确的方式实现了兔子数列的计算:

def rabbit_count(n):
    if n == 1 or n == 2:
        return 1
    else:
        return rabbit_count(n-1) + rabbit_count(n-2)

print(rabbit_count(12))

但是,请注意,上述递归方法虽然逻辑上正确,但是当n较大时会非常慢,因为它涉及大量重复计算。对于实际应用,推荐使用迭代法或者利用动态规划减少重复计算,例如:

def rabbit_count_iterative(n):
    if n == 1 or n == 2:
        return 1
    prev, curr = 1, 1
    for _ in range(3, n + 1):
        prev, curr = curr, prev + curr
    return curr

print(rabbit_count_iterative(12))

这个迭代版本效率更高,可以快速准确地计算出前12个月的兔子对数。

6.归并排序

见:归并排序详解(附python实现)_归并排序递归法实验结果python-CSDN博客

实例

#兔子数列
#正序,但是数字是反向的,如果从1开始便利那么只会返回1,return后不可继续执行
'''
例如输入12
顺序:12,11,10,9,8,7,6,5,4,3,2,1
'''
def contra(month):
    if month==0 or month==1:
        return 1
    else:
        return  contra(month-1)+contra(month-2)
print (contra(12))
def paix(li_1):
    li_1.sort()
def countoushu():
    count=0
    for i in range(1,101):
        if i%3==2:
            count+=i
    print (count)
countoushu()
def jiecheng(num):
    if num==3:
        return 3
    else:
        return num*jiecheng(num-1)
print (jiecheng(6))
# 计算1~100偶数之和
def contdouble():
    count = 0
    for i in range(1,101):
        if i%2==0:
            count+=i
    return count
contdouble()
#思路1 逆置==倒置
def huiwen(num):
    if num==num[::-1]:
        return '是回文数'
    else:
        return '不是回文数'
print (huiwen('123454321'))
#思路二 如果是偶数则是前面的等于后面的,如果是奇数那么中间数前面的等于后面的
def huiwen1(num):
    a=len(num)
    if (a%2==0):
        #字符串是一个可迭代对象
        if (num[:int(a/2)]==num[::-1][:int(a/2)]):
            print(num[:int(a / 2)-1:-1])
            return '是回文数'
        else:
            return '不是回文数'
    else:
        if (num[:int(a/2)]==num[:int(a/2):-1]):
            print (num[:int(a/2):-1])
            #或者可以写成 if (num[:int(a/2)]==num[::-1][:2]):
            return '是回文数'
        else:
            return '不是回文数'
print (huiwen1('12344321'))
#判断是否为三角形
def sanjiao(*args):
    if args[0] + args[1] >args[2] and args[1] + args[2] >args[0] and args[0] + args[2] >args[1]:
        return '是三角形'
    else:
        return '不是三角形'
print(sanjiao(3,4,5))
#求两个正整数的最小公倍数(肯定大于两个数的最大值)
def minbei(*args):
    a = max(args)
    while True:
        if a/args[0] == args[1] and a/args[1] == args[0]:
            return a
        else:
            a+=1
print (minbei(7,9))
def jiecheng(num):
    if num==1:
        return 1
    else:
        return num*jiecheng(num-1)
def maxlist(*args):
    a = max(args)
    b=min(args)
    return f'最大值{a}最小值{b}'
print (maxlist(4,5,6,7))
#查找字符串
#方法一
def findstr(string,value):
    if string.find(value):
        return '找到了'
    else:
        return '没找到'
print(findstr('hello word','word'))
#方法二
def findstr1(string,value):
    if value in string:
        return '找到了'
    else:
        return '没找到'
print(findstr1('hello word','h'))


评论