什么是指数移动平均线的“epsilon”?

时间:2017-10-31 14:28:35

标签: c++ floating-point precision moving-average

我在我的音频应用程序中应用Exponential Moving Average作为平滑参数的过滤器:

a0 = 0.01
z += a0 * (input - z);

Here's代码和第一步50步:

#include <iostream>

int main ()
{
    double a0 = 0.1;
    double input = 0.8;
    double z = 0.0;

    std::cout << "init z: " << z << std::endl << std::endl;

    for(int i=0; i < 50; i++) {
        z += a0 * (input - z);
        std::cout << z << std::endl;
    }

    std::cout << std::endl << "final z: " << z << std::endl;
}

我需要检查上一个平滑值是否与当前值相同,这意味着过滤器已经完成了#34;它的熏制过程,价值总是一样的。

但是z总是会epsiloninput不同,所以我无法检查input == z它始终是假的。 Here's一个例子,带有无限循环。

zinput之间的epsilon是什么?因此,如果它在该范围内,我可以检查并避免进一步的操作。

4 个答案:

答案 0 :(得分:2)

考虑比率&#34; new z&#34;到&#34;老z&#34;,少1:

(z + a(i - z)) / z - 1

(显然简化为ia / z - a)。如果这个数量小于1e-6,那么接受完成。如果z为零,则始终继续。将此乘法容差调整为适合您要求的容差。

(从科学角度来说,容差与数据流的标准偏差相关 - 我敢建议甚至比例 - 但我无法在不研究实际数据的情况下提供更多提示。 )

答案 1 :(得分:2)

对于音频应用程序,您需要考虑采样的位数,以了解结果何时无法听到。每个位表示2的幂。例如,16位将是2 16 或65536,因此适当的epsilon将是您的样本比例除以65536.对于20位,它是2 20 < / sup>或1048576。

这些限制明显大于大多数其他应用程序所需的限制。

答案 2 :(得分:1)

而是检查zinput之间的epsilon,您可以在z的新值与前一个值之间进行检查。

答案 3 :(得分:-4)

在C ++中有

std::numeric_limits<double>::epsilon()

返回机器epsilon,即1.0和浮点类型T可表示的下一个值之间的差值。

修改后的代码:

#include <iostream>

int main()
{
    int counter = 0;
    double a0 = 0.1;
    double input = 0.8;
    double z = 0.0;

    std::cout << "init z: " << z << std::endl << std::endl;

    while (true) {
        z += a0 * (input - z);
        std::cout << counter++ << " | process: " << z << std::endl;

        double eps = std::numeric_limits<double>::epsilon();
        double diff = abs(z - input);
        if (diff <= 2 * eps) {
            break;
        }
    }

    std::cout << std::endl << "final z: " << z << std::endl;
}