这个数学舍入函数如何工作?

时间:2014-09-20 16:07:06

标签: c math rounding

任何人都可以解释这个功能的作用吗?

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

2 个答案:

答案 0 :(得分: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。

对于双精度数1e-18,值1 lsb约为1.0。因此,我不认为使用double函数进行任何修改是必要的(当然,除了更改参数类型之外)。

答案 1 :(得分:1)

我想我应该回过头来补充以下细节。

虽然答案指的是将负零转换为正数并且对我有用,但对此更重要。

添加1e-18然后从浮点数中减去它确实从浮点数中消除了非常低的数字。这用于音频应用,因为过滤器可以通过不断划分浮子的功能来再循环小浮子,从而导致数量越来越少。一旦数字变得非规范化(如Caskey所提到的),许多cpus(包括x86)中该数字的处理速度变得慢了100倍。

通过添加比该数据类型的非正规大小数字大得多的数字,可以消除存储在该类型中的微小值。减去相同的较大值会导致类型保持为零,如果处理则不会影响处理速度。消除微小值的原因是类型中的显着精度不足以容纳非常小的值和刚刚添加的值。

例如:

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

通过40次函数将其除以10,得到1e-40的值。

v = 0.0100000 e-38(float类型的精度大约为8位小数,指数最多为38,所以在内存中看起来像我在这里写的那样)。

现在这是float类型的非正规值,并且会导致cpu非常缓慢地处理它。如何摆脱减速?把它归零。所以:

加1e-18;结果: 1.00000000 e-18(注意原始的1e-40太小而不能用8位有效数字表示,如果它已经拥有更大的1e-18值)。

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

因此我们产生零,消除了原始的非正规值,我们的cpu感谢我们。