我正试图摆脱我职能中的花车。
我有一个函数操作16位整数值,这是一个升级的8位值。然后将缩减的8位发送到输出。
我确定我不是很好解释。像这样:
int8 spot_value = 21; //arbitrary. just need a starting point
int16 running_value;
running_value = spot_value << 8; //multiply by 256 which is 5376
running_value += 154; //my upscaled value is now 5530
spot_value = running_value >> 8; //downscale again
如果我们使用浮点数,我的缩减值将是21.6,我可以轻松地将其舍入到22并转换为int8。但是它会截断到21,这是我不想要的。
如果它是一个浮点数但是没有将任何东西转换成浮点数(甚至是暂时的),是否有一种方法可以“整数”整数整数?
这可能比我想要的要简单得多。
答案 0 :(得分:8)
您可以为该值添加1/2。在你的缩放系统中,这是128。
int8 spot_value = 21; //arbitrary. just need a starting point
int16 running_value;
running_value = spot_value << 8; //multiply by 256 which is 5376
running_value += 154; //my upscaled value is now 5530
spot_value = running_value + 128; //add an additional 1/2 for rounding
spot_value = spot_value >> 8; //downscale again
...或
scale_shift = 8;
scale = 1 << scale_shift
round = scale >> 1;
int8 spot_value = 21; //arbitrary. just need a starting point
int16 running_value;
running_value = spot_value << scale_shift; //multiply by 256 which is 5376
running_value += 154; //my upscaled value is now 5530
spot_value = (running_value + round) >> scale_shift; //downscale again
根据戴维的答案,还是一个小技巧......
running_value = spot_value << scale_shift; //multiply by 256 which is 5376
running_value += 154; //my upscaled value is now 5530
spot_value = (running_value >> 8) + ((running_value >> 7) & 1)
答案 1 :(得分:3)
在缩减之前,只需在值中添加一些内容即可。也就是说,当降档8时,添加128
,它将导致舍入值。
对于一般情况,当缩小N位时,在缩小之前添加1 << (N-1)
以获得舍入值。
答案 2 :(得分:3)
running_value = spot_value << 8; //multiply by 256 which is 5376
running_value += 154; //my upscaled value is now 5530
if(spot_value & (1 << 7)) {
spot_value = (running_value >> 8) + 1; //downscale again, but add 1 since the top bit of removed was set, i.e. ">= 1/2"
} else {
spot_value = running_value >> 8; //downscale normally
}
答案 3 :(得分:2)
您应该检查一下您是否高于或等于running_value
以上的0.5。即:
int16 round = (running_value >> 7) & 1; // =1 if decimal part >= 0.5, =0 otherwise.
spot_value = running_value >> 8 + round; //downscale again
答案 4 :(得分:0)
我被烧伤的一件事
int8 spot_value = 21; //arbitrary. just need a starting point
int16 running_value;
running_value = spot_value << 8; //multiply by 256 which is 5376
你正在8位变量spot_value上做8的leftshift。您将值放在一个16位变量中,因此它应该可以正常工作。但是,如果将代码移植到新的微程序,或切换编译器,或更改优化,或将代码重构为内联等,则可能会无意中移出整个值。
基本上,它归结为不信任编译器。在嵌入式系统上,您没有gcc的健壮性。我通常使用累加器约定来补偿这个:
int8 spot_value = 21; //arbitrary. just need a starting point
int16 running_value;
running_value = spot_value; //load accumulator for multiply
running_value <<= 8; //multiply accumulator (which is 21) by 256
同样的原理适用于乘法和除法,特别是在改变位宽时。
答案 5 :(得分:0)
注意,只是对未定义的有符号整数进行右移。左移是定义的。有三种可能的行为:
1)编译器将使用'sign-extension'并使用原始MSB的值填充空出的MSB(您提供的代码所需的行为)。
2)填充空位,零
3)用一个
填充空出的位我认为可能但空位不可能是随机的。就个人而言,我从未观察过(1)以外的行为,但可能性存在,如果需要可移植性和稳健性,应予以考虑。
如前所述,使用*和/是一种解决方案。我已经观察到了许多编译器的生成代码,并且总是通过移位操作实现乘法或除以字面常数2的幂,如果在架构上它更有效;即使没有明确设置优化选项。