C++计算选4位组合数时输入大数值输出NaN的原因咨询
大整数输入输出NaN的原因分析
核心异常原因
你当前实现的固定选4位的组合数计算逻辑,是先分别计算n!和(n-4)!两个完整阶乘值再做除法,输入300、400等较大正整数时输出NaN,本质是浮点数溢出触发非法运算导致的:
- 所有浮点数类型的可表示数值都存在明确上限,以主流平台上最常见的80位扩展精度
long double为例,它能表示的最大有限值约为1.18×10^4932,而1755!的数值量级已经超过这个阈值,运算时会直接被标记为正无穷(inf)。 - 当输入n为300、400时,循环计算n!的过程中,乘积早早就超出了
long double的表示上限,存储n!的factorial变量会变为正无穷;同理存储(n-4)!的fac变量也会因为溢出变为正无穷。 - 根据IEEE 754浮点数运算标准,正无穷除以正无穷属于非法运算,该操作的返回结果就是
NaN(Not a Number,即非数值)。
输入79、98、100时能正常输出,是因为100!的量级仅约为9.3×10^157,远低于long double的可表示上限,不会触发溢出,因此可以得到正常计算结果。
修复方法
组合数C(n,4)的公式本身可以做约分,不需要计算完整的大阶乘:C(n,4) = n!/(4!*(n-4)!) = n*(n-1)*(n-2)*(n-3)/24
按照这个简化公式计算,完全不会出现大阶乘溢出的问题,哪怕n取到int类型的上限值也能正常运算,修正后的代码如下:
#include <iostream> #include <iomanip> using namespace std; int main() { int n; cout << "Enter a positive integer: "; cin >> n; long double result = static_cast<long double>(n) * (n-1) * (n-2) * (n-3) / 24.0; cout << "Com. of " << n << " = " << setprecision(13) << result; return 0; }
内容的提问来源于stack exchange,提问作者Leaven
相关产品推荐
相关产品推荐

