【问题标题】:Integers and float precision整数和浮点精度
【发布时间】:2010-12-26 19:11:29
【问题描述】:

这更像是一个数值分析而不是编程问题,但我想你们中的一些人能够回答它。

在两个浮点数的和中,是否有任何精度损失?为什么?

在浮点数和整数的和中,是否有任何精度损失?为什么?

谢谢。

【问题讨论】:

  • 套用那首伟大的涅槃歌曲标题...闻起来像青少年家庭作业。
  • 浮点数通过否定证明了上帝的存在,因为它们肯定是魔鬼的作品。
  • Bob:不,只是不要指望它们表现得像数学实体 :-) (嗯,对于大多数事情来说,它们是实数所做的相当好的近似值。陷阱只会出乎意料地咬你大多数时候)

标签: precision floating-accuracy


【解决方案1】:

两个浮点数相加,有没有精度损失?

如果两个浮点数的大小不同,并且都使用完整的精度范围(大约 7 个十进制数字),那么是的,您会在最后几个位置看到一些损失。

为什么?

这是因为浮点数以 (sign) (mantissa) × 2(exponent) 的形式存储。如果两个值具有不同的指数并且您将它们相加,那么较小的值将减少到尾数中的较少位数(因为它必须适应较大的指数):

PS> [float]([float]0.0000001 + [float]1)
1

在浮点数和整数的和中,是否有任何精度损失?

是的,一个普通的 32 位整数能够准确地表示不完全适合浮点数的值。浮点数仍然可以存储大约相同的数字,但不再精确。当然,这只适用于足够大的数字,即。 e.超过 24 位。

为什么?

因为 float 有 24 位精度,而(32 位)整数有 32 位。float 仍然能够保留幅度和大部分有效数字,但最后的位置可能会有所不同:

PS> [float]2100000050 + [float]100
2100000100

【讨论】:

  • 只是在最后一点“为什么?”上扮演魔鬼代言人。 24 位整数不是仍然准确吗?这不是信息如何表示的问题,而不是位数的问题吗? 128 位浮点数仍有可能不准确,不是吗?
  • Lazarus:当然,如果你的整数适合 24 位,那么 float 可以准确地表示它。 Lua 的类似原理以及它采用 double 作为唯一的数字数据类型:它可以处理高达 52 位的整数。
【解决方案2】:

精度取决于原始数字的大小。在浮点中,计算机内部将数字 312 表示为科学计数法:

3.12000000000 * 10 ^ 2

左侧的小数位(尾数)是固定的。指数也有上限和下限。这允许它表示非常大或非常小的数字。

如果你尝试将两个大小相同的数字相加,结果应该保持相同的精度,因为小数点不必移动:

312.0 + 643.0 <==>

3.12000000000 * 10 ^ 2 +
6.43000000000 * 10 ^ 2
-----------------------
9.55000000000 * 10 ^ 2

如果您尝试添加一个非常大和非常小的数字,您会失去精度,因为它们必须被压缩成上述格式。考虑 312 + 12300000000000000000000。首先,您必须缩放较小的数字以与较大的数字对齐,然后添加:

1.23000000000 * 10 ^ 15 +
0.00000000003 * 10 ^ 15
-----------------------
1.23000000003 <-- precision lost here!

浮点数可以处理非常大或非常小的数字。但它不能同时代表两者。

对于int和double的加法,int会立即变成double,那么上面的适用。

【讨论】:

    【解决方案3】:

    两个浮点数相加时,一般会出现一些错误。 D. Goldberg 的"What Every Computer Scientist Should Know About Floating-Point Arithmetic" 详细描述了效果和原因,以及如何计算误差的上限,以及如何推断更复杂计算的精度。

    整数加浮点数时,C++先将整数转换为浮点数,所以加了两个浮点数,同上原因引入错误。

    【讨论】:

      【解决方案4】:

      float 可用的精度是有限的,所以当然总是存在任何给定操作降低精度的风险。

      您的两个问题的答案都是“是”。

      如果您尝试将一个非常大的浮点数添加到一个非常小的浮点数,例如,您会遇到问题。

      或者,如果您尝试将整数添加到浮点数,其中整数使用的位数比浮点数可用于其尾数的位数更多。

      【讨论】:

        【解决方案5】:

        简短的回答:计算机表示一个位数有限的浮点数,这通常用mantissa and exponent完成,因此只有几个字节用于有效数字,其他用于表示位置小数点。

        如果您尝试添加(例如)10^23 和 7,那么它将无法准确地表示该结果。类似的论点适用于添加浮点数和整数 - 整数将被提升为浮点数。

        【讨论】:

          【解决方案6】:

          在两个浮点数的和中,是否有任何精度损失? 在浮点数和整数的总和中,是否有任何精度损失?为什么?

          并非总是如此。如果总和可以用您要求的精度表示,并且您不会得到任何精度损失。

          示例:0.5 + 0.75 => 没有精度损失 x * 0.5 => 没有精度损失(除非 x 太小)

          在一般情况下,添加浮点数的范围略有不同,因此存在精度损失,这实际上取决于舍入模式。 即:如果您要添加范围完全不同的数字,则会出现精度问题。

          非正规函数在极端情况下可以提供额外的精度,但会消耗 CPU。

          根据编译器处理浮点计算的方式,结果可能会有所不同。

          在严格的 IEEE 语义下,添加两个 32 位浮点数不应提供比 32 位更好的精度。 在实践中,可能需要更多指令来确保这一点,因此您不应依赖浮点的准确且可重复的结果。

          【讨论】:

            【解决方案7】:

            在这两种情况下都是:

            assert( 1E+36f + 1.0f == 1E+36f );
            assert( 1E+36f + 1 == 1E+36f );
            

            【讨论】:

              【解决方案8】:

              float + int 的情况与 float + float 相同,因为标准转换应用于 int。在 float + float 的情况下,这取决于实现,因为实现可能会选择以双精度进行加法。当然,存储结果时可能会有一些损失。

              【讨论】:

                【解决方案9】:

                在这两种情况下,答案都是“是”。将int 添加到float 时,整数会在添加之前转换为浮点表示。

                要了解原因,我建议您阅读此 gem:What Every Computer Scientist Should Know About Floating-Point Arithmetic

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2018-02-23
                  • 2015-07-01
                  • 1970-01-01
                  • 2016-06-01
                  • 1970-01-01
                  • 2010-10-05
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多