C++ 反转FFT时未获得准确数据
好吧,我想做的很简单。对一些随机数据应用FFT,然后对输出应用反向算法以返回输入。我正在为此使用C++ 反转FFT时未获得准确数据,c++,c,floating-point,fft,kissfft,C++,C,Floating Point,Fft,Kissfft,好吧,我想做的很简单。对一些随机数据应用FFT,然后对输出应用反向算法以返回输入。我正在为此使用kissFFT库 代码: 。如果你去底部,你会发现有317个不匹配。我还输出值之间的差异,即(in[].r-rec[].r)或(in[].I-rec[].I) 我接下来展示的是输入数据,其中白点表示实部,红点表示虚部 这是以紫色表示的FFT输出数据,以及以白色和红色表示的重建的数据 注意到细微的差别了吗?我猜这与浮点精度有关。 如何克服这个问题以获得与我使用FFT时完全相同的输入数据 编辑:我注
kissFFT
库
代码:
。如果你去底部,你会发现有317个不匹配。我还输出值之间的差异,即(in[].r-rec[].r)
或(in[].I-rec[].I)
我接下来展示的是输入数据,其中白点表示实部,红点表示虚部
这是以紫色表示的FFT输出数据,以及以白色和红色表示的重建的数据
注意到细微的差别了吗?我猜这与浮点精度有关。
如何克服这个问题以获得与我使用FFT时完全相同的输入数据
编辑:我注意到,在我的例子中,距离误差是[0,0.002]。因此,作为一种解决方法,我对重建的数据进行了四舍五入,得到了一个很好的结果。但还是。。。只有当我的数字的小数部分是0.0时,这才有效。你猜得对;浮点数的精度有限,在这个过程中会丢失一些输入精度。如果需要精确的输入,则需要某种任意精度的浮点库(例如,the)。您的猜测是正确的;浮点数的精度有限,在这个过程中会丢失一些输入精度。如果您想要精确的输入,您将需要某种任意精度浮点库(例如,the)。meh,使用另一个库修改一个库会很痛苦,因为我知道它们都不是我写的。任意精度库不足以提供精确的结果。FFT中使用的许多系数都是无理的(甚至是超越的)。因此,它们不能精确地表示为任何有限精度或基数。更高的精度只能减少误差,而不能消除误差。然而,在FFT中通常没有理由得到精确的结果。从真实世界(例如,通过麦克风)获得的任何数据都有测量误差,因此对其进行的任何处理都必须容忍误差。这只是一个多少的问题,将噪音保持在可接受的水平以下。因此,失去一些准确性是不可避免的?!好吧,如果你一定要得到精确的结果,你可以使用某种符号数学库meh,如果你知道我没有写这两个库,那么用另一个库来修改一个库会很痛苦。任意精度的库不足以提供精确的结果。FFT中使用的许多系数都是无理的(甚至是超越的)。因此,它们不能精确地表示为任何有限精度或基数。更高的精度只能减少误差,而不能消除误差。然而,在FFT中通常没有理由得到精确的结果。从真实世界(例如,通过麦克风)获得的任何数据都有测量误差,因此对其进行的任何处理都必须容忍误差。这只是一个多少的问题,将噪音保持在可接受的水平以下。因此,失去一些准确性是不可避免的?!如果你一定要得到精确的结果,你可以使用某种符号数学库
const int fft_siz = 512;
const int inverse = 1;
kiss_fft_cpx* in = (kiss_fft_cpx*)malloc(sizeof(kiss_fft_cpx) * fft_siz);
kiss_fft_cpx* out = (kiss_fft_cpx*)malloc(sizeof(kiss_fft_cpx) * fft_siz);
kiss_fft_cpx* rec = (kiss_fft_cpx*)malloc(sizeof(kiss_fft_cpx) * fft_siz);
kiss_fft_cfg cfg = kiss_fft_alloc(fft_siz, !inverse, NULL, NULL);
kiss_fft_cfg icfg = kiss_fft_alloc(fft_siz, inverse, NULL, NULL);
srand((unsigned int)time(NULL));
for(int i = 0; i < fft_siz; i++)
{
in[i].r = rand() % 256;
in[i].i = rand() % 256;
}
kiss_fft(cfg, in, out);
// scaling
for(int i = 0; i < fft_siz; i++)
{
out[i].r /= fft_siz;
out[i].i /= fft_siz;
}
kiss_fft(icfg, out, rec);
unsigned int count = 0;
for(int i = 0; i < fft_siz; i++)
if(in[i].r != rec[i].r)
{
count++;
printf( "in[%3d].r does not match rec[%3d].r :: %3d :: %f\n",
i, i, count, in[i].r - rec[i].r);
}
else if(in[i].i != rec[i].i)
{
count++;
printf( "in[%3d].i does not match rec[%3d].i :: %3d :: %f\n",
i, i, count, in[i].i - rec[i].i);
}
free(in);
free(out);
free(rec);
free(cfg);
free(icfg);
kiss_fft_cleanup();
in[ 0]: 71.000000 85.000000 -- out[ 0]: 127.095703 124.541016
in[ 1]: 248.000000 27.000000 -- out[ 1]: -7.083314 0.072701
in[ 2]: 64.000000 18.000000 -- out[ 2]: -3.770610 2.682554
in[ 3]: 6.000000 96.000000 -- out[ 3]: -7.929140 -2.897723
in[ 4]: 98.000000 23.000000 -- out[ 4]: -0.719621 -5.854260
in[ 5]: 250.000000 188.000000 -- out[ 5]: 0.397226 -1.248124
in[ 6]: 231.000000 3.000000 -- out[ 6]: -7.934285 -2.367196
in[ 7]: 6.000000 105.000000 -- out[ 7]: -0.317480 -2.955601
in[ 8]: 172.000000 143.000000 -- out[ 8]: -4.236186 3.911616
in[ 9]: 16.000000 134.000000 -- out[ 9]: -0.162577 -5.353521
in[ 10]: 230.000000 112.000000 -- out[ 10]: -4.703711 7.791993
in[ 11]: 5.000000 26.000000 -- out[ 11]: -2.636305 0.188381
in[ 12]: 16.000000 127.000000 -- out[ 12]: 1.137413 4.576081
in[ 13]: 112.000000 86.000000 -- out[ 13]: 0.978051 -0.408992
in[ 14]: 40.000000 23.000000 -- out[ 14]: 5.231920 -2.347566
in[ 15]: 75.000000 26.000000 -- out[ 15]: 0.009981 -2.091559
note ::count::difference
--------------------------------------------------------
in[ 1].r does not match rec[ 1].r :: 1 :: -0.000031
in[ 3].r does not match rec[ 3].r :: 2 :: -0.000015
in[ 4].i does not match rec[ 4].i :: 3 :: -0.000004
in[ 6].i does not match rec[ 6].i :: 4 :: -0.000008
in[ 7].r does not match rec[ 7].r :: 5 :: -0.000002
in[ 9].r does not match rec[ 9].r :: 6 :: -0.000015
in[ 11].r does not match rec[ 11].r :: 7 :: -0.000015
in[ 12].r does not match rec[ 12].r :: 8 :: -0.000015
in[ 13].i does not match rec[ 13].i :: 9 :: -0.000008
in[ 14].i does not match rec[ 14].i :: 10 :: 0.000008
in[ 15].r does not match rec[ 15].r :: 11 :: -0.000015