long double FactorialLD(long n)
{
long double result = 1;
if (n <= 0)
return 1;
for (long i = 2; i <= n; i++)
result *= i;
return result;
}
30!
返回
265252859812191058647452510846976
。但是,使用桌面计算器或https://www.calculatorsoup.com/calculators/discretemathematics/factorials.php返回
265252859812191058636308480000000
。为什么有这么大的差异,是什么原因造成的?CPU:IntelX86_64
OS:Ubuntu24.10
Compiler:G ++14.2.0
在X86-64 Linux上的GCC,
80位扩展精度格式。 这具有64位的意义,这还不足以准确表示
30!
,其价值小于2^108。
(如果您检查sizeof(long double)
long double
您会看到它是16,但这仅仅是出于对齐的原因。实际值仅使用80位,其他48个未使用的填充物。)
如果您具有真正的128位四倍精度,它具有113位的显着性(计算隐式领先1位),那么您确实能够获得30的确切值!这样。 例如,Linux上的ARM64使用Quad-Precision进行
long double
:try在Godbolt中。
(X86-64上的GCC的当前版本实际上确实对128位四分之一的精度算术有所支持,而不是通过_Float128
而是通过新的_Float128
类型。但是,在Godbolt上进行了try,仍然缺少的是标准库支持; 但是,请注意,当前没有主流CPU/FPU对128位四位数精度具有硬件支持,因此对该类型的计算都在软件中完成,并且相对较慢。 (为此,X86是唯一支持80位的主流平台,并且仅在其传统X87指令集中,因此它比单个(32位)或双重精度(64位)较慢慢(64位)带有更现代的SSE*说明。)