【问题标题】:How is the precision loss from integer to float defined in C++?在 C++ 中如何定义从整数到浮点的精度损失?
【发布时间】:2019-09-10 12:00:31
【问题描述】:

我对下面的代码 sn-p 有疑问:

long l=9223372036854775807L;
float f=static_cast<float>(l);

长值不能完全按照 IEEE754 表示。

我的问题是如何处理有损转换:

  1. 是否采用最接近的浮点表示?
  2. 是否采用了下一个更小/更大的表示?
  3. 还是采取了其他方法?

我知道这个问题 what happens at background when convert int to float 但这并不能回答我的问题。

【问题讨论】:

  • C++ 不强制要求 IEEE754,仅供参考。

标签: c++ floating-point rounding static-cast


【解决方案1】:

C++ 是这样定义转换的(引用最新的标准草案):

[conv.fpint]

整数类型或无作用域枚举类型的纯右值可以转换为浮点类型的纯右值。 如果可能,结果是准确的。 如果要转换的值在可以表示的值范围内但不能准确表示,则它是实现定义的下一个较低或较高可表示值的选择。 [ 注意:如果整数值不能精确地表示为浮点类型的值,则会出现精度损失。 ——尾注 ] 如果要转换的值超出可表示的值范围,则行为未定义。 如果源类型为 bool,则值 false 转换为 0,值 true 转换为 1。

IEEE 754 标准这样定义转换:

5.4.1 算术运算

应该可以从所有支持的有符号和无符号整数格式转换为所有支持的算术格式。只要值可以以两种格式表示,整数值就会从整数格式精确转换为浮点格式。如果转换后的值不能以目标格式精确表示,则根据适用的舍入方向属性确定结果,并且会出现第 7 条中规定的不精确或浮点溢出异常,就像算术运算一样。整数零的符号被保留。没有符号的整数零被转换为 +0。首选指数为 0。

舍入模式指定为:

4.3.1 舍入到最近的方向属性

  • roundTiesToEven,传递最接近无限精确结果的浮点数;如果包围不可表示的无限精确结果的两个最接近的浮点数同样接近,则应传递具有偶数最低有效数字的浮点数。

  • roundTiesToAway,传递最接近无限精确结果的浮点数;如果包围不可表示的无限精确结果的两个最接近的浮点数同样接近,则应传递幅度较大的浮点数。

4.3.2 有向舍入属性

  • roundTowardPositive,结果应该是最接近且不小于无限精确结果的格式的浮点数(可能是+∞)

  • roundTowardNegative,结果应为最接近且不大于无限精确结果的格式的浮点数(可能为 -∞)

  • roundTowardZero,结果应该是格式的浮点数,最接近且幅度不大于无限精确结果。

4.3.3 舍入属性要求

roundTiesToEven 舍入方向属性应是二进制格式结果的默认舍入方向属性。

因此,默认情况下,您的建议 1 将适用,但前提是尚未选择其他模式。


C++ 标准库从 C 标准继承 &lt;cfenv&gt;。此标头提供用于与浮点环境交互的宏、函数和类型,包括舍入模式。

【讨论】:

    【解决方案2】:

    here:

    整数或无范围枚举类型的纯右值可以转换为 任何浮点类型的纯右值。如果该值不能 正确表示,它是实现定义是否 最接近的较高或最接近的较低可表示值将是 已选择,但如果支持 IEEE 算法,则舍入默认值 到最近。如果该值不适合目标类型,则 行为未定义。如果源类型为 bool,则值为 false 转换为零,值 true 转换为一。

    关于 IEEE 754 的四舍五入规则,好像有five of them。但是,我找不到任何有关在哪种情况下使用哪些信息的信息。看起来这取决于实现,但是您可以在 C++ 程序中设置舍入模式,如 here 所述。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-02-01
      • 2021-05-09
      • 1970-01-01
      • 2018-08-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多