我发现了一个实现,其中为了获得值x的四分之一,使用以下代码在arm 32位处理器上运行。
//global typedef
typedef unsigned char uint8;
//Function definition
uint8 FindQuarter(void)
{
uint8 value, OneQuarter,ThreeQuarter;
value = 100;
OneQuarter = (value * 64) / 255;// why not "(value * 1)/4" or "value/4"
ThreeQuarter = (value *192) /255; //why not "(value * 3)/4"
return 1;
}
为什么有人想要使用64/255或192/255而不是1/4或3/4,尽管两者都会给出大致相同的结果。
注:计算精度在这里不是最重要的,允许有一点偏差。
最佳答案
原著作者所说的“四分之一”是什么意思?当计算某些值时,会出现一个模式:
f(0) = 0x00 (0)
f(1) = 0xC0 (192)
f(2) = 0x80 (128)
f(3) = 0x40 (64)
f(4) = 0x00 (0)
f(5) = 0xC0 (192)
...
f(254) = 0x80 (128)
f(255) = 0x40 (64)
这可以解释为给每个输入值分配一个字节域的“四分之一”,其中每个四分之一由该子集中的最低值定义。(这当然不是四除一。)
编辑
上面的答案不准确(最多)或者更可能是不正确的。
根据一条评论,我对
f()
的实现似乎不正确,计算的/ 255
部分被“优化”,并作为-1的有符号除法执行。typedef unsigned char uint8;
int main (void)
{
short ui16Value;
for(ui16Value = 0; ui16Value < 0x100; ui16Value++)
{
uint8 value = (uint8)ui16Value;
// definition of f():
uint8 quarter = (value * 64) / 255;
printf("f(%d) = 0x%2.2X (%u)\r\n", value, quarter, quarter);
}
return 0;
}
拆卸:
! uint8 quarter = (value * 64) / 255;
0xF48: MOV.B [W14+2], W5
0xF4A: MOV #0xC0, W4 <-- this looks odd.
0xF4C: MUL.SS W5, W4, W4
0xF4E: MOV.B W4, [W14+3]
上面突出显示的行看起来像是一个运算符精度问题,在方括号中的乘法之前,64被255==0xff==-1除以。
显式地将该值声明为无符号会导致所有值都为零。
! uint8 quarter = (value * 64) / (uint8)255;
0xF48: MOV.B [W14+2], W4
0xF4A: ZE W4, W4
0xF4C: SL W4, #6, W5
0xF4E: MOV #0xFF, W4
0xF50: REPEAT #0x11
0xF52: DIV.SW W5, W4
0xF54: MOV W0, W4
0xF56: MOV.B W4, [W14+3]
我可能需要查看正在使用的编译器版本的勘误表,或者尝试编译目标micrcontroller而不是模拟器。不管怎样,这对我来说都是件有趣的事情。