我正在尝试计算可变长度字中位的函数值。启动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.
答案 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
。
注意
ULONG_MAX + 1
,因为这会导致数字保持整数类型并回绕到零(因此在运行时会导致被零除错误)。 ULONG_MAX + 1.0
可能与64位计算机上的ULONG_MAX
相同它被称为定点算术,互联网和其他地方有很多资源可以很好地解释它。
答案 1 :(得分:2)
或者您可以使用ldexp()
:
double result = ldexp(data * scaling_factor, -significant_bits) ;
它的优势在于能够准确地表达你在做什么! (假设scaling_factor
是double
。)
它还避免了构建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
二进制工作的方式是每个位的权重是其后位的两倍,因此您不需要像往常一样遍历这些位。