sqrt函数返回值强制转换为整数导致的程序异常问题
完全平方数判断失效及循环异常问题排查
问题代码
#include <stdio.h> #include <stdlib.h> #include <math.h> int main() { double a, b, c; for (a = 1; a < 333; a++) { for (c = 335; c < 998; c++) { if ((sqrt(a) != (int) sqrt(a)) || (sqrt(c) != (int) sqrt(c))) continue; b = 1000 - c - a; if ((c * c) == (a * a) + (b * b)) break; } } printf("%.0lf + %.0lf + %.0lf = 1000\nProduct: %.0lf\n", a, b, c, a * b * c); system("pause"); return 0; }
问题描述
这段代码意图寻找满足a+b+c=1000且c²=a²+b²的勾股数,同时要求a和c是完全平方数,但运行后得到的a、c是循环的最大值,且完全平方数的判断逻辑失效——比如a=332时,sqrt(a)被错误识别为整数,实际计算值应为18.248288,却被当成18.0处理。
问题根源
- 浮点数精度丢失:用
double类型存储整数a、c,循环中a++、c++的浮点数递增会导致精度误差。当数值较大时,double无法精确表示所有整数,比如332可能被存储为接近但略小的数值,导致sqrt(a)的计算结果出现偏差,后续与强制转换后的int值比较时误判为相等。 - 错误的完全平方数判断逻辑:直接用
sqrt(a) != (int)sqrt(a)的方式判断,依赖浮点数的精确相等比较,而浮点数运算本身存在精度误差,很容易出现误判。 - 循环未正确终止:即使找到符合条件的数,内层循环break后外层循环仍会继续执行,最终覆盖为循环的最大值。
修复方案
- 将a、b、c改为
int类型,彻底避免浮点数精度问题; - 用整数运算实现完全平方数判断:计算
k = sqrt(x)后,验证k*k == x(注意k需为整数); - 找到符合条件的数后,同时终止内外层循环。
修正后的代码
#include <stdio.h> #include <stdlib.h> #include <math.h> // 判断是否为完全平方数 int isPerfectSquare(int x) { if (x < 0) return 0; int k = (int)sqrt(x); return k * k == x; } int main() { int a, b, c; int found = 0; // 标记是否找到结果 for (a = 1; a < 333; a++) { if (!isPerfectSquare(a)) continue; // 先判断a,减少内层循环次数 for (c = 335; c < 998; c++) { if (!isPerfectSquare(c)) continue; b = 1000 - c - a; // 确保b是正整数,且满足勾股定理 if (b > 0 && c*c == a*a + b*b) { found = 1; break; } } if (found) break; // 找到结果后终止外层循环 } if (found) { printf("%d + %d + %d = 1000\nProduct: %lld\n", a, b, c, (long long)a*b*c); } else { printf("No valid solution found.\n"); } system("pause"); return 0; }
说明
- 新增
isPerfectSquare函数,用整数运算验证完全平方数,避免浮点数误差; - 提前判断a是否为完全平方数,减少不必要的内层循环;
- 加入
found标记,找到结果后立即终止所有循环; - 输出乘积时用
long long类型,避免整数溢出。
内容的提问来源于stack exchange,提问作者idk.mp3
相关产品推荐
相关产品推荐

