我已经提炼出一个等式:
speed = ( ( rear_wheel_speed_a + front_wheel_speed_a ) << 10 ) +
( ( rear_wheel_speed_b + front_wheel_speed_b ) << 2 );
但出于某种原因我得到了意想不到的结果,所以我一定做错了。这开始是这样的:
speed = ((((rear_wheel_speed_a * 256 + rear_wheel_speed_b) / 16) +
((front_wheel_speed_a * 256 + front_wheel_speed_b) / 16)) / 2) * 128;
这是完全不起作用的版本。它们不是数学上的等价物吗?
所有值都是16位整数。示例数据集是:
rear_wheel_speed_a = 0x03;
rear_wheel_speed_b = 0x6F; //<-- I originally swapped
front_wheel_speed_a = 0x02; //<-- these two values. Sorry!
front_wheel_speed_b = 0xE2;
归结为6468的答案。但在第一个等式中,我的应用程序表现得好像它至少小3%或更大。我这样说是因为这是一个嵌入式应用程序,我无法确认计算结果,只能测试它是否在“正常”的某个范围内。当我使用第二个等式时,它属于参数,但是我的“简化”(位移)方程式并不是这样,我认为我必须做错误的转换(或者我简化了错误,但我对其进行了三次检查)。
非常感谢您,谢谢。
答案 0 :(得分:12)
问题是你得到了溢出。虽然您转换的等式在数学上是正确的,但是您的某些临时值高于您存储它们的带符号的16位整数。
具体而言,有问题的部分是
( rear_wheel_speed_a + front_wheel_speed_a ) << 10
使用示例输入,结果值为0x1C800 - 大于无符号的16位整数!
原始等式似乎已经考虑到了这一点。降档时,有些值会略微失去精度,但这比整数溢出要好。所以我建议使用原始等式,但你可以用乘法替换乘法和除法,当然:
((((rear_wheel_speed_a << 8) + rear_wheel_speed_b) >> 4) + (((front_wheel_speed_a << 8) + front_wheel_speed_b) >> 4)) << 6;
另一个注意事项:您的输入front_wheel_speed_b已经溢出,除非它应该是负数。
答案 1 :(得分:4)
从第二个公式中,我假设您将2个16位值分成8位a和b:
rear_wheel_speed = 0x0302
front_wheel_speed = 0x6fe2
和您使用的公式可以简化为speed = (front_speed+rear_speed)*4
。
根据您的值,0x6fe2 * 4只能适合16位,因此可以用16位算术计算该值。但是这些值看起来像是它们的部分排列错了,我感觉实际值是0x036f和0x02e2(或0x03ea和0x026f) - 这些值彼此接近,应该从两个车轮的速度预期。
此外,您的公式似乎更好,因为它不会导致除法运算的精度损失。但请记住,如果您使用的是良好的编译器(对于嵌入式应用程序并不总是如此),它通常会在可能的情况下将divide / multiply转换为自身的移位
答案 2 :(得分:0)
你想要的是rear_wheel_speed和front_wheel_speed的平均值,缩放到16位。由于它们是16位值,因此总和为17位,因此您必须移位结果以避免溢出。
您的初始公式将每个速度设置为12位(xxx / 16),然后是12位的平均值,然后乘以128.这将需要19位:初始公式将溢出更大的值。
为了得到16位没有溢出的平均值,我建议如下(假设你的评论中的值为正值):
rear_wheel_speed_h = (rear_wheel_speed_a << 7) | (rear_wheel_speed_b >> 1)
front_wheel_speed_h = (front_wheel_speed_a << 7) | (front_wheel_speed_b >> 1)
speed = rear_wheel_speed_h + front_wheel_speed_h
这将在16位上产生没有溢出的结果。每个xxx_wheel_speed_h都是15位。
答案 3 :(得分:0)
在原始表达式中,除法运算符丢弃了低位,但很明显,你的替代品并没有丢弃任何低位的位数,所以仅此意味着它们不能等效!
“rear_wheel_speed_b) / 16)
”在对它们执行任何操作之前丢弃rear_wheel_speed的4个低位,并且“front_wheel_speed_b) / 16)
”丢弃front_wheel_speed的4个低位。然后“/ 2)
”运算符丢弃总和的低位。
如果你在表达式中添加了一些东西,那么你只能得到完全相同的结果:
speed = ((((rear_wheel_speed_a * 256 + rear_wheel_speed_b) / 16) +
((front_wheel_speed_a * 256 + front_wheel_speed_b) / 16)) / 2) * 128;
变为
speed = ( ( rear_wheel_speed_a + front_wheel_speed_a ) << 10 ) +
( ( ( ( rear_wheel_speed_b & ~0x0F ) + ( front_wheel_speed_b & ~0x0F ) ) & ~1) << 2 );
换句话说,
是((((x * 256) / 16) / 2) * 128)
== ((((x << 8) >> 4) >> 1) << 7)
,
是的,((((x << 8) >> 4) >> 1) << 7)
== (x << 10)
,
是的(((y / 16) / 2 ) * 128 )
== (( y >> 5 ) << 7)
,
但是没有 (( y >> 5 ) << 7)
!= (y << 2)
!
和没有 (((a + b) >> 1) << 7)
!= (((a >> 1) << 7) + (((b >> 1) << 7)
!