【问题标题】:printing the largest single-precision floating point number打印最大的单精度浮点数
【发布时间】:2015-02-02 15:47:01
【问题描述】:

我是来求知的。
我正在尝试理解浮点数。
我试图弄清楚为什么当我打印最大的浮点数时,它不能正确打印。

2-(2^-23)                          Exponent Bits
1.99999988079071044921875 * (1.7014118346046923173168730371588e+38) = 
    3.4028234663852885981170418348451e+38

这应该是最大的单精度浮点数:

340282346638528859811704183484510000000.0

所以,

float i = 340282346638528859811704183484510000000.0;
printf(TEXT, "Float %.38f", i);
Output: 340282346638528860000000000000000000000.0

显然这个数字正在四舍五入,所以我想弄清楚到底发生了什么。

我的问题是: Wikipedia 文档指出,3.4028234663852885981170418348451e+38 是 IEEE-754 定点可以表示的最大数字。

浮点寄存器中存储的数字是否=0 11111111 11111111111111111111111,只是显示不正确?

如果我写printf(TEXT, "Float %.38f", FLT_MAX);,我会得到相同的答案。 也许我正在使用的计算机不使用 IEEE-754?

我了解计算错误,但我不明白为什么数字 340282346638528860000000000000000000000.0 是可以准确表示的最大浮点数。

也许尾数 * 指数导致计算错误?如果这是真的,那么340282346638528860000000000000000000000.0 将是可以忠实表示而不会出现计算错误的最大数字。我想这是有道理的。只需要祝福。

谢谢,

【问题讨论】:

  • “0 11111111 11111111111111111111111”是 NAN。怀疑你想要“0 11111110 11111111111111111111111”
  • FLT_MAX 就是你想的那样。您的printf() 显示了它的近似值。要查看确切FLT_MAX 的十进制值,您需要使用不同的代码。
  • 维基百科还说“这给出了 6 到 9 位有效十进制数字的精度”,因此在日常使用中作为某个附近值的近似值,试图打印所有数字,就好像它是一个特定的整数一样量级有点傻。之前的 10^~30 个整数都不可表示。有趣的是 printf 显示了通常在双精度值中有意义的位数 - 我的猜测是您的实现将浮点数转换为双精度,生成一个合理的表示,并用 0 填充到请求的长度.
  • @Tony D printf(TEXT, "Float %.38f", i);ifloat 转换为 double,然后将其传递给 printf()printf() 没有收到 float
  • @chux: 是的,当然......所以显示比这更低的精度是不合理的......而且显然实现显示更多是毫无意义的。

标签: c++ c printf ieee-754


【解决方案1】:

看起来罪魁祸首是printf()(我猜是因为float在传递给它时被隐式转换为double):

#include <iostream>
#include <limits>

int main()
{
    std::cout.precision( 38 );
    std::cout << std::numeric_limits<float>::max() << std::endl;
}

输出是:

3.4028234663852885981170418348451692544e+38

【讨论】:

  • 我将不得不尝试。如果这是值,那么它必须是 printf() 语句。
  • 我使用您的代码得到的答案略有不同。 34028234663852887000 ...所以它必须与编译器/计算机有所不同。有没有,或者你可以用 printf() 语句试试吗?
  • Re "我猜是因为 float 被隐式转换...":传递给 printf()float 对象`,它确实转换为 double,不会改变 打印。部分问题在于printf() 所做的事情,但这不是由于隐含的转换。
【解决方案2】:

floatbinary32,最大的有限float

340282346638528859811704183484516925440.0

printf("%.1f", FLT_MAX) 没有义务精确打印到 38+ 位有效数字,因此看到如下输出并不意外。

340282346638528860000000000000000000000.0

printf() 将浮点精确地打印到DECIMAL_DIG 有效数字。 DECIMAL_DIG 至少 10。如果指定的重要性超过DECIMAL_DIG,则符合要求的printf() 可能会在某个时候舍入结果。 C11dr §7.21.6.1 6 详细介绍。

【讨论】:

  • 有趣的是,该问题声称它是 340282346638528859811704183484510000000.0 - 但鉴于该问题确实是在寻求对 printf 显示的精度低得多的解释,因此该值的偶然性较小。不错的答案。我怀疑 printf() 可能被允许显示更多,甚至有义务......只是这个特定的实现选择不......但我还没有找到参考。
  • @Tony D 找到了规范并修改了帖子。该规范有点技术性,所以我没有引用它,但 IMO,它暗示至少 DECIMAL_DIG 数字必须准确呈现。显示更多有效数字,它们必须是正确的(边界下一个最高或下一个最低)。
  • 哦很酷 - 很高兴知道。你对这个问题很感兴趣:-)。干杯。
  • Slava 使用 cout 得到了正确答案,所以一定是 printf() 语句。我没有验证有效性,但在他和你的帖子之间关于“printf may round and some point”。应该是这个原因。谢谢
  • @Christopher J. Holland 是的,printf() 只需要打印到DECIMAL_DIG(来自&lt;float.h&gt;)有效数字,之后它可能只是零。不同的平台提供不同级别的精度。注意:FLT_MAX 之前的下一个较小的 float 是 340282326356119256160033759537265639424.0,因此一旦通过 8 个 MSDigit,其余数字就会迅速失去重要性。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-06-09
  • 2021-07-25
  • 2016-09-02
  • 1970-01-01
  • 2011-05-17
  • 2020-08-04
相关资源
最近更新 更多