如何解决这段C代码中的Floating Point Exception问题?
错误原因分析
- 整数溢出触发非法运算:
int类型的最大值为2147483647,而13的阶乘(6227020800)已远超该范围,溢出后会变成未定义的负数或乱码值。当这些异常值参与comb函数的乘法运算时,可能出现fact(x-y)*fact(y)的结果为0的情况,此时执行整数除法会触发除零错误,对应你看到的floating point exception (core dumped)(部分系统会将整数除零归类为该信号)。 - 即使未触发除零,溢出后的阶乘值完全失真,也会导致组合数计算结果错误,无法正确判断是否大于1000000。
修复方案
优化版代码(适配n=100的场景)
抛弃直接计算大阶乘的方式,改用递推式计算组合数,同时利用组合数对称性减少计算量,还能提前终止判断避免不必要的大数值运算:
#include <stdio.h> long long comb(int x, int y); int greater(int x, int y); int main() { int count = 0; for (int n = 1; n <= 100; n++) { for (int r = 0; r <= n; r++) { if (greater(n, r)) { count++; } } } printf("%d\n", count); return 0; } // 优化组合数计算:用递推式+对称性,避免超大阶乘 long long comb(int x, int y) { // 利用C(n,k)=C(n,n-k)减少计算次数 if (y > x - y) { y = x - y; } long long result = 1; for (int i = 1; i <= y; i++) { // 先乘后除,保证每一步都是整除 result = result * (x - y + i) / i; // 提前终止:只要结果超过1e6,直接返回 if (result > 1000000) { return result; } } return result; } int greater(int x, int y) { return comb(x, y) > 1000000 ? 1 : 0; }
关键修复细节
- 改用
long long类型存储组合数计算结果,提升数值容纳范围。 - 递推式计算组合数,避免直接计算超大阶乘导致的溢出。
- 利用组合数对称性减少循环次数,提升效率。
- 提前终止判断,一旦中间结果超过1e6就停止计算,避免无效运算。
内容的提问来源于stack exchange,提问作者Alpha Beta
相关产品推荐
相关产品推荐

