Tentei calcular o fatorial em um sistema de 64 bits usando o seguinte trecho de código:
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!
retorna 265252859812191058647452510846976
. No entanto, usando calculadora de desktop ou https://www.calculatorsoup.com/calculators/discretemathematics/factorials.php retorna 265252859812191058636308480000000
. Por que há uma discrepância tão grande e o que está causando isso?
CPU: Intel x86_64
SO: Ubuntu 24.10
Compilador: g++ 14.2.0
Com gcc no Linux x86-64,
long double
é o formato de precisão estendida de 80 bits . Este tem um significando de 64 bits que não é suficiente para representar exatamente30!
, cujo valor é um pouco menor que 2^108.(Se você verificar,
sizeof(long double)
verá que é 16, mas isso é simplesmente por questões de alinhamento. O valor real usa apenas 80 bits e os outros 48 são preenchimentos não utilizados.)Se você tivesse precisão quádrupla de 128 bits verdadeira , que tem um significando de 113 bits (contando o bit inicial implícito 1), então você realmente seria capaz de obter o valor exato de 30! dessa forma. Por exemplo, ARM64 no Linux usa precisão quádrupla para
long double
: try on godbolt .(As versões atuais do gcc em x86-64 realmente têm algum suporte para aritmética de precisão quádrupla de 128 bits, não via,
long double
mas via o novo_Float128
tipo. Experimente em godbolt . No entanto, o que ainda falta é suporte à biblioteca padrão; por exemplo, você ainda não pode inserir ou emitir_Float128
comprintf
,iostream::operator<<
, etc.)Esteja ciente, no entanto, de que nenhuma CPU/FPU convencional atualmente tem suporte de hardware para precisão quádrupla de 128 bits, então os cálculos nesse tipo são todos feitos em software e serão relativamente lentos. (A propósito, o x86 é a única plataforma convencional que suporta 80 bits, e apenas em seu conjunto de instruções legado x87, então é um pouco mais lento do que precisão simples (32 bits) ou dupla (64 bits), o que pode ser feito com as instruções SSE* mais modernas.)