【问题标题】:What is a suitable tolerance for expecting n floats to sum to 1期望 n 个浮点数总和为 1 的合适容差是多少
【发布时间】:2019-01-02 08:10:32
【问题描述】:

我有 n 个浮点数,它们的总和应为 1,每个浮点数可以取 0 到 1 之间的任何值。我想检查它们的总和是否为 1,但由于 FP 数字不准确,检查总和 == 1 不会总是工作。

因此我想检查 Math.abs(sum - 1)

更新:我理解为什么浮点数不精确,并且我知道我可以以更精确的方式处理概率。我只想了解更多关于花车的信息。

更新 2:如果我从数学上考虑,浮点数总和为 1(例如 0.1 + ... + 0.1)

【问题讨论】:

  • 你的浮点精度是多少?
  • 您的应用程序的目的是什么,float 和 double 用于科学计算,也就是说,它们计算有效数字并与这些有效数字相加/求和。如果您想要精确使用 int log 或更大的数字使用 BigDecimal
  • 另一个问题询问如何解决精度问题,我想了解结果有多不精确,这就是为什么我认为这是一个不同的问题。
  • @mkjh:这不是that problem 的副本。该问题取决于它的解释方式,询问单次乘法中的误差(即 ½ ULP)或一般计算中的误差(不能作为一般问题回答;误差范围可能从零到无穷大和 NaN )。这个问题提出了一个受限制的可回答问题。

标签: java floating-point floating-accuracy


【解决方案1】:

是的,可以通过使用固定精度浮点数进行加法来确定最大可能的“错误”。

但是,此分析的结果对于 epsilon 来说不是有用的值。

考虑以下示例:

float a = 1.0E-37f;
float b = Float.MIN_VALUE;

System.out.println((a+b) == a);
System.out.println(a);
System.out.println(1.0f - a);

打印出来:

true
1.0E-37
1.0

因此,如果您对1.0E-37f 执行任意数量的Float.MIN_VALUE 加法,则与1.0f 的总和之差仍为1.0f

这表明,当使用无限精度时,由有限精度浮点数引起的最大误差实际上是 1.0 的总和 - 显然,这作为 epsilon 没有用。只有在“足够好”的要求已知时才能确定有用的 epsilon - 这取决于您要将结果用于什么,并且通常无法回答。


当然,上面的示例有点做作,因为它突出了在您的情况下可能无法实现的最坏情况,具体取决于n 的实际值。

正如@EricPostpischil 在 cmets 中提到的,

[0,1]中任意两个数相加最大误差为½ ULP(½),加法有n−1次,所以总误差最多为(n−1)•½•ULP(½ )。

从这个公式可以看出,n 值会导致1.0 的错误。 (您可能已经注意到,我在示例中选择了相对较小的值 - 需要很多值才能加起来为 1)。

输入一些数字:

int n = 33554433;
System.out.println((n-1)*0.5*Math.ulp(0.5f));

产量

1.0

如果您的n 低得多,或者您知道输入数字的进一步限制但尚未告诉我们,则可能会为错误获得更有用的上限。


然而,我的观点仍然成立 - 虽然知道这个上限可能很有用,但它不能用作验证一个值通常“足够好”的 epsilon。

【讨论】:

  • 这是不正确的;最大误差不是 1,并且不可能进行任意数量的加法,因为问题表明有 n 个要加法。一个容易证明的界来自于这样一个事实½•ULP(½)。 (ULP(½) 是格式的“epsilon”的一半。)但是,可以通过显示 n 个数字总和为 1 的约束阻止它们的值始终获得单个数字的最大误差来改进这个界限加法。
  • 一、问题用n参数化;该问题要求给定 n 的界限,而不是所有可能 n 的整个集合的界限。因此,对于不大的n,误差界限是(n-1)•½•ULP(½),并且1是不可得到的。其次,对于较大的 n,界限不同,但仍小于 1。给定 [0, 1] 中的 n 个浮点值,其和为 1,其中至少一个必须为正,因此使用浮点计算的和-point 必须是正数,因此 1 和计算的和之间的差必须小于 1。因此错误永远不会是 1。这个答案是不正确的。
  • 是的,给定一些正数 aba+b 的计算和可能是 a,因此错误是 b 的 100%。但这不是问题要问的。
  • @EricPostpischil 我编辑了答案。当我读到它时,这个问题有两个部分。首先,是否可以确定最大误差(答案:是),其次,这是一个用于接受或拒绝结果的有用 epsilon,我对此的回答是“不,一般而言”。
  • 上面给出的错误永远不会是1的证明只是一个开始,一个原则证明。即使对于非常大的 n,我怀疑可以证明一个显着的界限。加零没有错误,所以我们可以只考虑非零值的数量。如果这个数字很大,很多数字都很小,相加的误差很小。可能的总误差可能有很大的界限。 OP 提出的问题很有趣,不应忽视。
【解决方案2】:

这个问题提出了许多值得探索的案例。我在下面写了一些材料,但这只是一个起点。

在这个答案中,我使用了以下条件:

  • 数字以某种 IEEE-754 二进制浮点格式表示并执行算术运算,使用舍入到最近的偶数。
  • 我们有一个数字序列s0, s1, s2,… sn−1,在那种格式中,每个都是 (0, 1]并且其精确的数学和为 1。

(请注意,零被排除在区间之外。零的存在不会影响任何最终的总和,因为添加零不会改变值,因此任何包含零的序列都可以通过删除零来简化为没有它们的序列.)

定义:? 是 1 和下一个更大的可表示值之间的差,也称为最低精度单位 (ULP)。 (请注意,ULP 通常是 1 的最小精度单位,而 ULP(x) 是 x 大小的数字的最小精度单位,即,按浮点指数缩放。)

定义:u是单位四舍五入,是[1, 2)中数字四舍五入可能出现的最大误差。在四舍五入模式中,u 是 ½?。在定向舍入模式中,例如朝向无穷大或朝向零,u 是?。 (目前,我不考虑定向舍入模式。)

按最小位排序是准确的。

定义:数字的后一位是其表示中最低有效1的位置值。例如,如果二进制浮点数为 1.011•2-5,则其后一位为 0.001•2-5 = 2-8支持>.

假设我们使用这个算法对数字求和:

  • 令 S 为包含序列中数字的集合。
  • 选择S中任意两个元素ab,其后一位不大于任何其他元素。
  • 将 S 中的 ab 替换为 ab 的计算总和。
  • 重复直到 S 包含一个元素。

S 中剩余的数正好是 1,没有错误。

证明:

  • 如果 S 中的某个元素 a 的尾随位小于 1 且不大于 S 中任何其他元素的尾随位,则一定有其他元素 b 在 S 中具有相同的尾随位。这是必要的,因为所有元素的总和为 1,因此该位置的最少非零位的总和必须为零 - 1 位不能是奇数。
  • 两个数之和最多为大数的两倍,因此 ab 之和的前导位最多比领先一点。但是它们的尾一位和为零,所以和的尾位至少高一个位置,所以精确和的宽度最多是更宽的操作数的宽度,所以它是完全可表示的,并且计算的和是准确的。
  • 所以算法中的所有算术运算都是精确的,所以最终的和是精确的。

按大小排序

假设数字按升序排列,我们依次相加:S0 = s0, S1 = S0 + s1 sub>, S2 = S1 + s2,… Sn-1 = Sn -2 + sn-1。这里,Si 代表精确的数学和。让 Ti 成为我们通过使用浮点运算执行相同算法得到的值。这是在计算一组数字的总和时减少舍入误差的众所周知的技术。

产生每个 Ti 的加法错误的界限是 uT。对于这个初步的分析,我将假设 uSi 充分近似 uSi。那么总误差的界限是 uSii 求和,不包括 i=0(因为将 S0 设置为 s0 没有错误;第一次加法发生在 S1 sub>),我会写 sum(uSi).

这等于 u sum(Si)。而 sum(Si) = S1 + S2 + … Sn−1 = (s0) + (s0 + s1) + (s0 + s1 + s2) + ... = (n-2)•s0 + (n-2)•s em>1 + (n−3)•s2 + 1•sn-1。允许 [0, 1] 中的任何实数值,当 s0 和剩余的 si 都是 1/(n-1)。鉴于我们的要求值在 (0, 1] 中,这是无法实现的,并且浮点格式的约束也可能会阻止它,但它给出的总和比浮点值所能提供的要大,所以它仍然是有效界限(忽略 TiSi)。

那么 sum(Si) 是 n-1 个数从 1/(n -1) 到 1,所以它们的和是 ½(1/(n-1) + 1) • (n-1),我们的界错误是 u • ½(1/(n-1) + 1) • (n-1) = ½联合国

因此,在添加一百万个数字时,我们可以预期最大误差约为 250,000 ?。 (同样,我们假设 Si 代表 T i。)典型的错误当然会小得多。

请注意,这只是一个界限的推导。上面未检查的其他考虑因素可能会进一步限制错误。例如,如果使用 IEEE-754 基本 32 位二进制浮点时 n 为 2149,则上述界限为 2147 .然而,问题的约束要求每个 si 正好是 2-149,在这种情况下 T224-1 是 2-125 (尚未发生错误),但随后的每个 由于四舍五入,Ti 也是 2-125(将 2-149 添加到 2-125 得到 2-125 由于精度),所以最终结果为 2-125,即误差为 1-2−125,远小于2147

任意排序

假设我们无法控制顺序,必须按照给定的顺序添加数字。 (0, 1)中任意两个数相加的最大误差为½u,因此前n-2次相加的总误差为½u(n-2)。最后的加法可能会产生 1,所以它的舍入误差受 u 的限制,不一定是 ½u,所以总误差受 ½u 的限制>(n−2) + u = ½un.

讨论

排序加法与任意排序的界限相同。一个原因是排序加法在 uSi 中以代数方式使用舍入误差 u,而任意排序利用 [½, 1) 中的所有数字的舍入误差最多为 ½u 的事实——它使用区间的底部,而排序的加法通道使用比例。因此,可以改进排序的加法推导。此外,最坏的情况是所有数字都相等,这意味着排序没有任何好处。一般来说,排序会改善错误。

负错误和正错误的行为是不对称的,应该分开考虑。

【讨论】:

  • 请注意,?,即 1 与其后继者(即 ulp(1))之间的距离,称为 机器 epsilon。 ULP 表示单元在最后一个位置;它总是相对于某个数字?,因此应该写“ulp(?)”,但是当数字是隐式的(或者binade是固定的)时,可以写“ulp”。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-03
  • 2011-01-11
  • 2021-11-15
  • 1970-01-01
相关资源
最近更新 更多