C如何打印超大号?

时间:2015-01-17 15:21:16

标签: c linux windows gcc compilation

这段代码如何打印这么大的数字?我在Ubuntu 14.04(gcc 4.8.2)上尝试过它。 它在任何编译器的MS Windows上都不起作用(即使是MinGW,也称为“gcc for Windows”)。为什么呢?

#include <stdio.h>
#include <math.h>
int main()
{
    printf("%.0f\n",pow(2,500));
}

Ubuntu输出:

3273390607896141870013189696827599152216642046043064789483291368096133796404
674554883270092325904157150886684127560071009217256545885393053328527589376

Windows输出:

3273390607896141900000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000

(仅为清晰起见而添加换行符。)

3 个答案:

答案 0 :(得分:7)

如OP提示并由@ user300234评论,2^500是一个501位数字,但这不是问题。

pow(2,500)返回double,约3.27e150,通常为binary64。此类型支持大约15-17个十进制数字的精度。因此对于 near 3.27e150附近的数字,打印更多17个有效数字通常并不重要。它远小于DBL_MAX,可能约为1.798e308

这里的诀窍是pow(2,500) 完全可以表示为浮点double(binary64)。这可能会让人觉得double具有数百位精度 - 但事实并非如此。

两种不同的编辑处理double以不同的方式转换为文本,一旦打印了17个左右的数字 - 这是C规范允许的。正确数字的最小数量为DBL_DECIMAL_DIG - 在两个系统上可能为17。

考虑打印 next 更大double。虽然下一个双打可以打印150个左右的数字,但通常这些额外的数字通过DBL_DECIMAL_DIG只是许多应用程序的噪音。

// 2 ^ 500
327339060789614 187001318969682759915221664...
// next
327339060789614 259685191399243448970154045...

答案 1 :(得分:4)

MinGW也使用的Microsoft Visual C运行时库(msvcrt.dll)仅支持最多17位数的精度,因为这足以唯一地标识(IEEE 754)double

但好消息:使用VS2015 CTP4编译的代码产生与Ubuntu示例相同的输出。如果您正在使用MinGW-w64,则可以在将__USE_MINGW_ANSI_STDIO1编译器选项包含在同一输出之前将<stdio.h>定义为-D

答案 2 :(得分:0)

这不是一个新的答案,但与其他人已经说过的内容略有不同:

区别在于pow()函数:区别在于printf()函数。 Ubuntu printf()正在打印pow(2,500)的确切十进制值。 Windows printf()正在打印一个正确到17位十进制数的近似值。

在某种意义上,这两种实现都是正确的;但我会说Windows printf()更多正确。这就是原因:

如果您关心的精度超过17位,则不应使用double

通常,大多数双重计算的结果仅在前17位中正确。 (pow(2, n)是一个非常特殊的情况,答案对于范围内的任何 n 都是完全正确的。)通过打印非常大的双精度的精确十进制值,Ubuntu库愚弄你;假设你有

double a = ...;
double b = ...;
double c = a*b;

printf("%f", c);

您不想知道c的确切价值,因为对于大多数abc 不等于a*b:它只是a * b的近似 - 一个近似值,精确到大约17位有效数字。

如果你需要超过17位数的精度,那么你应该使用像GMP这样的扩展精度数学库(https://gmplib.org/