在浮点精度成为问题之前可以添加多少个浮点数

mar*_*rsh 1 c++ floating-point precision

我目前正在 MS 中记录一些帧时间而不是滴答声。我知道这可能是一个问题,因为我们将所有帧时间(以 MS 为单位)加在一起,然后除以帧数。由于浮点精度,这可能会导致不良结果。

将所有滴答计数加在一起然后在最后转换为 MS 会更有意义。

但是,我想知道少量样本的实际差异是什么?我希望有 900-1800 个样本。这会是一个问题吗?

我做了这个小例子并在 GCC 4.9.2 上运行它:

// Example program
#include <iostream>
#include <string>

int main()
{
    float total = 0.0f;
    double total2 = 0.0f;

    for(int i = 0; i < 1000000; ++i)
    {
        float r = static_cast <float> (rand()) / static_cast <float> (RAND_MAX);
        total += r;
        total2 += r;
    }

    std::cout << "Total: " << total << std::endl;
    std::cout << "Total2: " << total2 << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

结果:

总计:500004 总计2:500007

因此,据我所知,使用 100 万个值,我们不会失去很多精度。虽然我不确定我写的内容是合理的测试还是实际测试我想要测试的内容。

所以我的问题是,在精度成为问题之前,我可以添加多少个浮点数?我希望我的值在 1 到 60 MS 之间。我希望结束精度在 1 毫秒内。我有 900-1800 个值。

示例值:15.1345f 为 15 毫秒。

Eri*_*hil 5

反例

使用以下关于问题陈述的假设(时间有效地以 0.06 等值表示 60 毫秒),如果我们将 0.06 转换为float并添加 1800 次,计算结果为 107.99884796142578125。这与数学结果 108.000 相差 0.001 以上。因此,计算结果有时会与数学结果相差 1 毫秒以上,因此在这些条件下无法实现问题中想要的目标。(进一步细化问题陈述和替代计算方法可能能够实现目标。)

原始分析

假设我们在 [1, 60] 中有 1800 个整数值转换为floatusing float y = x / 1000.f;,其中所有操作都使用 IEEE-754 基本 32 位二进制浮点数实现,并具有正确的舍入。

1 到 60 的转换float是精确的。除以 1000 的误差最多为 ½ ULP(.06),即 ½ • 2 ?5 • 2 ?23 = 2 ?29。1800 个这样的错误最多等于 1800 • 2 ?29

随着结果float值相加,每次相加最多可能存在 1/2 ULP 的误差,其中 ULP 是当前结果的 ULP。对于宽松的分析,我们可以将其与最终结果的 ULP 绑定,最终结果的 ULP 最多约为 1800 • .06 = 108,其 ULP 为 2 6 • 2 ?23 = 2 ?17。因此,1799 次加法中的每一个误差最多为 2 ?17,因此加法中的总误差最多为 1799 ? 2 ?18

因此,除法和加法期间的总误差最多为 1800 • 2 ?29 + 1799 • 2 ?18,约为 0.006866。

这是一个问题。我希望对加法中的错误进行更好的分析将使误差界限减半,因为它是从 0 到总数的等差数列,但仍然存在高于 0.003 的潜在误差,这意味着总和可能为关闭几毫秒。

请注意,如果将时间添加为整数,则最大的潜在总和为 1800•60 = 108,000,远低于float(16,777,217) 中无法表示的第一个整数。将这些整数相加float是没有错误的。

这个 0.003 的界限足够小,以至于对问题的一些额外约束和一些额外的分析可能,只是可能,将它推到 0.0005 以下,在这种情况下,计算结果将始终足够接近正确的数学结果,四舍五入计算结果到最接近的毫秒将产生正确的答案。

例如,如果知道时间范围从 1 到 60 毫秒,但总时间总是小于 7.8 秒,这就足够了。