广义冰雹数收敛性验证与保持模式数量统计开发需求
广义冰雹数收敛模式统计
问题描述
课堂中讨论的冰雹数规则为:
当$x_{n-1}$为奇数时,$x_n = 3x_{n-1} + 1$;当$x_{n-1}$为偶数时,$x_n = x_{n-1}/2$。这类序列最终会收敛到循环模式 4→2→1→4→2→1……,这类重复循环被称为收敛模式。
我们需要测试广义冰雹数:当$x_{n-1}$为奇数时,$x_n = ax_{n-1} + b$;当$x_{n-1}$为偶数时,$x_n = x_{n-1}/2$,其中$a$、$b$为正整数。要求针对所有$a、b≤10$的组合,判断序列是否收敛,并统计序列收敛到的不同保持模式的数量。
示例
当$a=3$、$b=5$时:
- 从1出发的序列:1→8→4→2→1,这是一种保持模式;
- 从5出发的序列:5→20→10→5,这是另一种保持模式。
现有代码分析
你提供的现有Python代码存在以下核心问题:
- 收敛判断逻辑错误:
validation函数仅判断序列是否回到起始值,但收敛模式可能是多元素循环(如4→2→1),该逻辑无法识别这类有效收敛模式。 - 统计方向偏离需求:代码统计的是“能回到起始值的起始数数量”,而非任务要求的“不同收敛模式的数量”。
- 无依据的奇偶组合过滤:代码中对
i(即a)和j(即b)的奇偶组合过滤没有逻辑支撑,会直接跳过部分有效组合。 - 终止条件不合理:步数限制为100,部分收敛较慢的序列会被误判为不收敛。
def validation(x,a,b): steps = 1 start = x set1 = set() while x not in set1: steps += 1 set1.add(x) if x % 2 == 0: x = x//2 else: x = a*x + b if steps == 100: break; if x == start: return True else: return False def hailstone(number): List = [] for i in range(1,11): for j in range(1,11): count = 0 for x in range(1, number+1): if (((i%2 != 0 ) and (j%2 == 0)) or ((i%2 == 0 ) and (j%2 != 0))): break else: if validation(x,i,j): #calling 'validation' to check if it is true count += 1 List.append([i,j,count]) return(List) pattern_count = hailstone(number = 100) print(pattern_count)
修正后的代码实现
以下代码针对需求重新设计,能够正确识别收敛模式并统计不同模式的数量:
def find_cycle(start_x, a, b, max_steps=1000): """ 寻找从start_x出发的广义冰雹序列的循环模式 返回:循环的标准化元组(以循环中最小元素为起点),未找到则返回None """ sequence = [] current = start_x while current not in sequence: sequence.append(current) if len(sequence) > max_steps: return None # 超过步数限制,判定为不收敛 # 计算下一个数 if current % 2 == 0: current = current // 2 else: current = a * current + b # 提取循环部分 cycle_start_idx = sequence.index(current) cycle = sequence[cycle_start_idx:] # 标准化循环:以循环中的最小值为起点,避免同一循环的不同起始被重复统计 min_val = min(cycle) min_idx = cycle.index(min_val) normalized_cycle = tuple(cycle[min_idx:] + cycle[:min_idx]) return normalized_cycle def count_convergent_patterns(max_ab=10): """统计a、b≤max_ab时的收敛情况及不同模式数量""" results = [] for a in range(1, max_ab + 1): for b in range(1, max_ab + 1): unique_patterns = set() # 测试1到100的起始数,覆盖大部分可能的模式 for x in range(1, 101): cycle = find_cycle(x, a, b) if cycle: unique_patterns.add(cycle) # 记录该组合的结果 results.append({ "a": a, "b": b, "收敛状态": "收敛" if unique_patterns else "不收敛", "不同模式数量": len(unique_patterns) }) return results # 执行统计并打印结果 stats = count_convergent_patterns() for res in stats: print(f"a={res['a']}, b={res['b']} | {res['收敛状态']} | 不同模式数量: {res['不同模式数量']}")
代码说明
find_cycle函数:- 跟踪序列的所有值,当出现重复值时提取循环部分;
- 对循环进行标准化处理:将循环旋转到以最小元素为起点,确保同一循环的不同起始形式(如4→2→1和2→1→4)被视为同一模式。
count_convergent_patterns函数:- 遍历所有a、b≤10的组合;
- 对每个组合,测试1到100的起始数,收集所有不重复的标准化循环模式;
- 记录每个组合的收敛状态和模式数量。
内容的提问来源于stack exchange,提问作者user21247582
相关产品推荐
相关产品推荐

