繁体   English   中英

在32位计算机上使用48位

[英]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.81e142.81e14 / 1000 = 2.81e11 32位数字可以容纳4.29e9因此除以1000不会解决任何问题-该数字将不合适。

就是说,不要除以1000,再除以1024。这与将数字右移10相同。或者,如果可以,则丢弃10个最低有效位。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM