打印非常大的浮点数

fre*_*low 13 c c++ floating-point standards printf

#include <stdio.h>
#include <float.h>

int main()
{
    printf("%f\n", FLT_MAX);
}
Run Code Online (Sandbox Code Playgroud)

GNU的输出:

340282346638528859811704183484516925440.000000
Run Code Online (Sandbox Code Playgroud)

Visual Studio的输出:

340282346638528860000000000000000000000.000000
Run Code Online (Sandbox Code Playgroud)

C和C++标准是否允许这两种结果?或者他们是否要求特定的结果?

请注意FLT_MAX = 2^128-2^104 = 340282346638528859811704183484516925440.

Oli*_*rth 6

我认为C99标准的相关部分是7.19.6.1第13页的"推荐做法":

对于e,E,f,F,g,和G转换,如果显著小数位数最多 DECIMAL_DIG,那么结果应该进行正确舍入.如果有效十进制数的数量大于DECIMAL_DIG但是源值可以用DECIMAL_DIG数字精确表示,那么结果应该是具有尾随零的精确表示.否则,源值由两个相邻的十进制字符串L < U限定,两者都有DECIMAL_DIG有效数字; 结果十进制字符串D的值应满足L <= D <= U,并额外规定错误应具有当前舍入方向的正确符号.

我的印象是,这允许在这种情况下可能印刷的一些余地; 所以我的结论是VS和GCC都符合这里的要求.

  • @ybungalobill:浮点不代表间隔.它代表可能是精确的二元有理数或根据您的用法进行四舍五入的结果.使用浮点执行区间运算实际上非常困难*(并且要么快速扩展区间,要么需要不断更改舍入方向以及考虑舍入模式的实现). (8认同)
  • 根据IEEE浮点运算标准754-2008的规定,浮点数据仅表示特定数字(和NaN),而不是间隔.根据第3.3节,所代表的数据为+0; -0; 形式(-1)**s*b**e*m的数字,其中s是0或1,b,e和m是特定浮点类型的合适的基数,指数和有效数; +无穷大,无穷大,安静的NaN和信号Nan.浮点运算的结果由操作数表示的各个数字决定,而不是由它们周围的间隔决定. (6认同)
  • @ColeJohnson:没有更精确的.GNU欺骗你认为它有,但它的结果甚至比MSVC更糟糕.浮点表示*间隔*,而不是数字.所以340282346638528859811704183484516925440,340282346638528859811704183484516925450和340282346638528860000000000000000000000都是相同的浮点值(对于64位ieee).[一个更好的浮点格式化rountine实际上是给你最短表示的那个](http://florian.loitsch.com/publications/dtoa-pldi2010.pdf). (5认同)
  • 它们并非无足轻重的数字.问题是值"1e-20"已经四舍五入.GNU libc(不是GCC; GCC是一个编译器,与`printf`行为无关)版本打印浮点表达式的确切值.如果你的意思是代表数字1e-20的值,那么最后的数字可能对你没有意义,但是'printf`无法知道你打算作为1e-20的近似值而不是浮动的确切值点表达.MSVCRT行为无论如何都没有益处; 它只是懒惰. (5认同)
  • 它们都是正确的,只有一个更精确. (2认同)
  • @FredOverflow:GNU结果是正确的值,但两者似乎都符合标准中的要求和推荐的实践. (2认同)
  • @R.:表示间隔!=区间算术.它表示间隔,但算术被定义为对所述间隔中的代表的常规算术.它与区间算术不同,但它再次与问题无关.请阅读一些文献.如果你不喜欢链接的文章,你可能会喜欢[这一个](http://www.cs.washington.edu/education/courses/cse590p/590k_02au/print-fp.pdf),或者参考Knuth. (2认同)