AWK脚本提取质数异常:输出结果不符预期求排查
AWK质数检测脚本问题排查
我编写了一段AWK脚本,用于提取文件中的质数并打印,代码如下:
#!/bin/awk -f function is_prime(n) { if (n <= 1) return 0; if (n == 2) return 1; for (i = 2; i <= sqrt(n); i++) { if (n % i == 0) { return 0; } } return 1; } { gsub(/[^[:digit:]]/, " "); for (i = 1; i <= NF; i++) { if (is_prime($i)) { print $i; } } }
测试文件内容:
Math is179day foun193dary 18 nachum17 19
预期输出:
179 193 17 19
实际输出:
14 5 5
补充:调整print语句后,甚至只输出3行空白,没有数字。
问题根源
- 变量作用域冲突:AWK中函数内未声明的变量默认是全局变量。
is_prime函数使用了全局变量i,而主循环中也用i作为字段索引。调用is_prime时,函数会修改全局i的值,导致主循环遍历逻辑混乱,这是输出错误数字的核心原因。 - 浮点精度问题:使用
sqrt(n)作为循环上限,sqrt返回浮点数,可能因精度丢失导致循环提前终止,无法正确判断质数。
修正后的代码
#!/bin/awk -f function is_prime(n, i) { # 声明局部变量i,避免全局作用域冲突 if (n <= 1) return 0; if (n == 2) return 1; if (n % 2 == 0) return 0; # 提前排除偶数,优化性能 for (i = 3; i*i <= n; i += 2) { # 用i*i <=n替代sqrt,消除浮点精度问题 if (n % i == 0) { return 0; } } return 1; } { gsub(/[^[:digit:]]/, " "); for (j = 1; j <= NF; j++) { # 主循环改用j作为索引,彻底避免变量重名 if (is_prime($j)) { print $j; } } }
修正说明
- 在
is_prime函数参数列表后添加, i,将i声明为局部变量,隔绝全局作用域干扰。 - 主循环索引改用
j,彻底避免和函数内变量重名的问题。 - 用
i*i <= n替代i <= sqrt(n),消除浮点计算带来的精度误差。 - 新增偶数判断逻辑,提前排除大于2的偶数,优化质数判断的执行效率。
内容的提问来源于stack exchange,提问作者Nessya Nakache
相关产品推荐
相关产品推荐

