2014-09-20 61 views
5

任何人都可以解释这个函数做什么?这个数学舍入函数是如何工作的?

static inline void round_to_zero(volatile float *f) 
{ 
    *f += 1e-18; 
    *f -= 1e-18; 
} 

我的意思是除了添加1e-18并再次减去它,我明白这一点。但我不明白它会对传递给它的浮点数有什么影响。我试图理解它的原因是我在使用这个函数(我已经从浮动转换)的一些代码中使用双打。它的音频编码,和上面的函数来源于此库:

https://github.com/swh/lv2/blob/master/include/ladspa-util.h

我想知道是否会在双工作作为是,或需要修改的额外精度的双了。我怀疑这会摧毁最后几位数据,如果他们在那里将他们从浮动中清除掉,尽管我不太明白。但我想象如果这是它的作用,我将需要改变指数以适应双倍。

TIA,Pete

+0

看起来像这是一个严重优化的代码,它依赖于IEEE754处理非正规数与代码处理的预期数据类型(http://en.wikipedia.org/wiki/Denormal_number)。除此之外,我无法理解它。 – caskey 2014-09-20 16:13:59

+0

@caskey'float'非正规数字比那个小。 – ouah 2014-09-20 16:19:51

回答

1

以下代码演示了该函数的功能。

int main(void) 
{ 
    float a; 

    a = -1.0; 
    a /= 1e100; 
    printf("%f\n", a); 

    round_to_zero(&a); 
    printf("%f\n", a); 
} 

你需要知道的事情是,IEEE-754浮点数有两个可能的值0。有一个positive 0和一个negative 0round_to_zero函数将负数0转换为正数0.

对于双精度数1.0,值1e-18大约为1 lsb。所以我不认为有必要对double使用该函数进行修改(当然,除了改变参数类型之外)。

+0

谢谢 - 你能解释它是如何做到这一点的吗?为什么添加1e-18并减去它有这种效果,我想知道它对可能传递的全部数字有什么影响。如果1e-18的值为1 lsb的双精度值,那么对于代码所设计的浮点数,它必须远远小于这个值,所以我想知道该函数对浮点数与双精度浮点数有什么不同?因为我真的不明白(虽然我理解需要删除标记),但我怀疑可能会使使用双打的代码执行不同(未检测到)的细微差异。 – Pete 2014-09-20 17:14:57

+0

@Pete - 这个想法是,如果你以负数0开始,那么加1e-18会给你一个小的正数,而减1e-18会给你一个正数0.如果你用任何其他数字开始,加法和减法1e-18对数字没有影响。无论如何,这似乎是理论。 – user3386109 2014-09-20 17:47:11

1

想到我应该回到这添加以下细节。

虽然答案指的是负零转换成积极的是真实的,是对我很有用,那里有比这更多了。

添加1e-18然后从浮点数中减去它确实会从浮点数中清除非常低的数字。这用于音频应用程序,因为滤波器可以通过不断分割浮动的函数来循环小浮点数,从而实现更小的浮点数。一旦数字变得非规范化(正如Caskey提到的那样),那么在许多CPU(包括x86)中处理该数字的速度就会降低100倍。

通过添加比该数据类型的非正规尺寸数字大得多的数字,可以清除存储在该类型中的微小值。减去相同的较大值会导致类型为零,如果处理速度不影响处理速度。消除微小值的原因是类型中的重要性和精度不够大,无法保持非常小的值和刚刚添加的较大值。

例如:

从音频样本开始,值为1.0f。

把这个通过一个函数40次,除以10,得到1e-40的值。

V = 0.0100000 C-38(浮子类型有大约8小数精度,和高达38的指数,所以看起来在存储器中作为我在这里写入它)。

这是一个float类型的非规范值,并且会导致cpu非常缓慢地处理它。如何摆脱减速?让它为零。所以:

加1e-18;结果: 1.00000000 e-18(请注意,如果原始1e-40太小,无法在8位数字有效数字中表示,如果它已经保存了更大的1e-18数值)。

然后减去1E-18值: 0.00000000 E-0

因此,我们产生零,消灭了原来的规格化值,我们的CPU感谢我们。