[英]Working with 48bit on 32bit machine
我这里有一个小型的“ PLC”,在32位MCU上运行。 我可以定义的最大变量是uint32(无符号int)。 我正在读一米,通过串行线以6个字符给我48位值。 我现在通过移动字符将这个值存储在两个32位中。
T1Low = (unsigned int) mybuffer[3] << 24 | (unsigned int) mybuffer[2] << 16 |
(unsigned int) mybuffer[1] << 8 | (unsigned int) mybuffer[0];
T1High = (unsigned int) mybuffer[5] << 8 | (unsigned int) mybuffer[4];
但是我想将48bit值除以1000,然后将其保存为一个32bit(因为除后,它将给我足够的精度)。
理论上类似
unsigned int result = (T1High << 32 | T1Low) / 1000;
当然,由于班次太大,这是行不通的。有什么办法可以做到这一点?
编辑:分辨率的说明:仪表以kWh为单位,但是该值以Wh为单位。 最大值为9 999 999,足以保存32位。 但是从仪表上我会得到9 999 999 000 ...所以我需要在最后减少3个零。
EDIT2:cmaster给出了正确答案:)如果有人只想将代码放入两行,则:
unsigned int value1;
unsigned int value2;
unsigned int value3;
value2 += (value1%1000) << 16;
unsigned long result = ((value2 / 1000) << 16) | ((value3 + ((value2 % 1000) << 16)) / 1000);
从数学上讲, T1High << 32 | T1Low
T1High << 32 | T1Low
等于
T1High * 2**32 + T1Low
和的除法可以用除法的和代替,这可以使我们得出以下公式:
((T1High * 2**16 * 2**16) + T1Low) / 1000
(T1High * 2**16 / 1000 * 2**16) + (T1Low / 1000)
(((T1High << 16) / 1000) << 16) + (T1Low / 1000)
但是,这可能会导致失去一些精度:
4823248397 = ((1123 << 32) + 123899) / 1000
4823187579 = (((1123 << 16) / 1000) << 16) + (123899 /1000)
我将以2 ^ 16为底进行除法:将您的值分成三个16位的块,将它们存储在uint32_t
变量中,然后执行以下操作:
uint32_t result1 = value1/1000;
uint32_t remainder = value1 - result1*1000;
value2 += remainder << 16;
uint32_t result2 = value2/1000;
remainder = value2 - result2*1000;
value3 += remainder << 16;
uint32_t result3 = value3/1000;
当然,您也可以将其表述为循环,但我怀疑这样做是否值得。 此方法尽可能精确。 缺点是,它需要三个除法和两个乘法,如果计算资源紧张,可能会导致性能问题。
但我想将48bit值除以1000,然后将其保存为一个32bit
您的规格没有意义。 2^48 = 2.81e14
和2.81e14 / 1000 = 2.81e11
。 32位数字可以容纳4.29e9
因此除以1000不会解决任何问题-该数字将不合适。
就是说,不要除以1000,再除以1024。这与将数字右移10相同。或者,如果可以,则丢弃10个最低有效位。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.