C - 没有循环的位操作

时间:2014-08-02 16:50:43

标签: c bit-manipulation bit

我正在尝试计算可变长度字中位的函数值。启动MSB,如果位为1,则该值为1/2 ^ i。该值乘以比例因子

示例:110010 这将是(1/2 + 1/4 + 1/64)* scaling_factor

我用for循环编程了它;任何想法如何避免循环?

这是代码:

double dec_bnr (unsigned long data, int significant_bits, double scaling_factor)
{
    unsigned int temp;
    unsigned int bnr_locmask = 0x8000000;
    temp = data & bnr_locmasks[significant_bits-1];
    double result = 0;

    for (int i=0; i<significant_bits; i++){
        if((temp & bnr_locmask)==bnr_locmask){
            result+=pow (0.5, i+1);
        }
        bnr_locmask = bnr_locmask >> 1;
    }
    return result * scaling_factor;
}

提前谢谢!

修改:感谢您的回答;但是,我想说的不是你的建议。请允许我添加一个例子:     数据= a0280

A       2   4   8   16  32  64  128 256 512 1024    2048    4096    8192
1/A     0,5     0,125                               0,000488281     0,00012207
data    1   0   1   0   0   0   0   0   0   0        1        0         1   0000000

result = scaling_factor*Sum(data/A)

如果该位置的位为1,我们只考虑值1 / A.

3 个答案:

答案 0 :(得分:3)

如果没有循环,它实际上很容易做到:

double dec_bnr (unsigned long data, double scaling_factor)
{
    return data*scaling_factor/(ULONG_MAX+1.0);
}

值得注意的是此代码中会发生什么。首先,将data转换为double以匹配scaling_factor然后将这些数字相乘,然后我们进行进一步的缩放除以ULONG_MAX+1.0,这也将转换为分开前double。 注意

  1. 这不能是ULONG_MAX + 1,因为这会导致数字保持整数类型并回绕到零(因此在运行时会导致被零除错误)。
  2. 解释为double的数字ULONG_MAX + 1.0可能与64位计算机上的ULONG_MAX相同
  3. 它被称为定点算术,互联网和其他地方有很多资源可以很好地解释它。

答案 1 :(得分:2)

或者您可以使用ldexp()

  double result = ldexp(data * scaling_factor, -significant_bits) ;

它的优势在于能够准确地表达你在做什么! (假设scaling_factordouble。)

它还避免了构建2的大功率((double)(ULONG_MAX + 1)不太有用!)和划分,或者pow(2.0, -significant_bits)和乘法的任何问题。


进一步思考......这当然是等同的:

  double result = ldexp((double)data, -significant_bits) * scaling_factor ;

但你可以将{二分点转换“与scaling_factor(一次)混为一谈:

  double scaling_factor_x = ldexp(scaling_factor, -significant_bits) ;

然后转换就是:

  double result = (double)data * scaling_factor_x ;

答案 2 :(得分:0)

这或类似的东西应该等同于你正在做的事情:

(double)data / 0x100000000 * scaling_factor

二进制工作的方式是每个位的权重是其后位的两倍,因此您不需要像往常一样遍历这些位。