【问题标题】:Floating-Point Arithmetic = What is the worst precision/difference from Dec to Binary?浮点算术 = Dec 到 Binary 的最差精度/差异是多少?
【发布时间】:2011-08-24 02:08:58
【问题描述】:

众所周知,decimal fractions(如 0.1),当存储为 floating point(如 double 或 float)时,将在内部以“二进制格式”(IEEE 754)表示。并且有些小数部分不能直接用二进制格式表示。

我不明白的是,这个“转换”的精度:

1.) 浮点本身可以​​有精度(即“显着”)?

2.) 而且从十进制小数到二进制小数的转换也有精度损失?

问题:

从十进制分数转换为浮点分数时,最坏情况下的精度损失是多少(对于“所有”可能的十进制分数)?

(我想知道这一点的原因是,在将小数与二进制/浮点小数进行比较时,我需要考虑精度......以确定两个数字是否相同。我希望这个精度为尽可能紧密/精确(decimal fraction == binary fraction +/- precision)

示例(仅假设)

0,1 dec => 0,10000001212121212121212 (binary fraction double) => precision loss 0,00000001212121212121212
0,3 dec => 0,300000282828282 (binary fraction double) => precision loss  0,000000282828282

【问题讨论】:

  • 这是绝对差异,还是百分比差异?您的示例显示了绝对差异,但在 某些 情况下找到最大百分比差异情况可能更有意义。
  • 你好,德兰,非常好的观点。也许百分比精度损失会更相关?
  • 请避免使用多个问号。一个就够了。

标签: java math floating-point decimal fractions


【解决方案1】:

我并不完全清楚您的目标是什么,但您可能会对以下论文感兴趣,该论文讨论了二进制/十进制转换中涉及的许多准确性问题,包括困难案例列表。

弗恩·帕克森和威廉·卡汉。 一个测试IEEE十进制-二进制转换的程序。 1991 年 5 月 22 日 http://www.icir.org/vern/papers/testbase-report.pdf

【讨论】:

    【解决方案2】:

    浮点数越大越不准确(正向和负向)。这是因为浮点值是指数格式。

    但是,无论它有多大,小数点使用的小数位数越多,它就会变得越来越精确。

    因此,最差的精度差异将是您使用的任何浮点类型的数值限制。

    【讨论】:

      【解决方案3】:

      由于我们从小就被教导数数,因此很难完全理解二进制分数的精确特性。问题是分数只能是计数系统的功率。说起来似乎很明显,但基本问题是十进制将事物分为十,而二进制将事物分为二(半)。

      在大多数情况下,您在计算中需要浮点值有两种情况:何时是货币值,何时不是。后者的范围可以从来自旋转轴上的编码器的输入到虚拟空间中的位置以用于处理到图形引擎。小数值是二进制的没有问题,因为它确实是一个小数值。这也是 FPU 在几年前开始流行于 3D 图形的部分原因。

      问题在于表示货币,其中小数部分实际上是离散的十进制单位。在现实世界中,您可以拥有 0.01 美元(取决于它是哪一美元!),但这很难用二进制准确表示。这就是为什么你永远不应该使用二进制浮点来表示货币。

      如果您在十进制和二进制浮点之间进行转换并尝试进行比较,我会看看您为什么要进行转换以及比较应该达到什么目的。

      【讨论】:

      • 不幸的是,浮点问题更严重。你通常有一个符号*base^exponent 格式,所有这些都是二进制的。
      【解决方案4】:

      如果十进制值落在可表示的浮点值范围内,并且您的语言/实现具有正确舍入的转换(很多可以,有些不可以),则此类转换的错误以 1/ 为界2 连续浮点数之间的距离,或“ulp”(最后位置的单位)。

      ulp的relative大小在2的精确幂和下一个更大的数之间最大,因此达到了decimal和double之间转换的最大relative误差当输入仅略小于 1 + 1/2 ulp 或按 2 的幂缩放的值时。这种值的一个例子是:

      1.0000000000000001110223024625156540423631668090820312
      

      (这几乎无限小于 1 + 2^-53)。

      由于转换产生的误差有一个相对的界限,因此绝对误差显然会随着我们将该值按 2 次方放大而变大。

      当然,如果一个数字超出可表示值的范围(太大或太小),那么所有精度都会丢失。将1e400 转换为double 产生infinity;没有我们实际输入的痕迹。同样,将1e-400 转换为double 会产生零。

      【讨论】:

        【解决方案5】:

        数字越大,精度损失就越高(但它可能正是您指定的数字)。

        您不仅可以在 java 中将非常小的数字存储为浮点数或双精度数,还可以将非常大的数字存储为 9*10^105。

        而且我希望这种精度尽可能严格/精确

        您可以选择 BigDecimal,您可以在其中指定您希望获得的精确度,但您当然会受到 RAM、CPU 时间和 JVM 的限制。

        您只对绝对精度感兴趣,还是对相对精度感兴趣?

        比较精度差异:

        a = 100000000000000,0000000000000001 
        b = 100000000000000,0000000000000002
        
        layoutHonkyTonkA= 0,0000000000000001 
        layoutHonkyTonkB= 0,0000000000000002
        

        绝对精度差异相同,但相对精度差异很大。

        【讨论】:

          猜你喜欢
          • 2014-10-07
          • 2011-05-18
          • 1970-01-01
          • 2011-09-22
          • 1970-01-01
          • 1970-01-01
          • 2012-03-14
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多