2017-04-06 46 views
0

我在这里有一个小型“PLC”,它运行在32位MCU上。 我可以定义的最大变量是uint32(unsigned int)。 我正在读一米,它给了我6位字符(通过串行线)的48位值。 我现在有这个值存储在两个32位通过移动字符。在32位机器上使用48bit

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]; 

但我想用1000除以48位值,并将其保存到一个32位(因为分之后,它会给我足够的精度)。

从理论上讲是这样

unsigned int result = (T1High << 32 | T1Low)/1000; 

当然,这并不因为太大转变的工作... 有什么办法如何做到这一点?

编辑:分辨率的描述: 在千瓦时电表措施,但该值以Wh给出。最大值是9 999 999,这足以保存在32位。但从米我会得到9 999 999 000 ...所以我需要在最后削减3个零..

编辑2:正确的答案是由cmaster :) 如果有人想把代码只有2行,则:

unsigned int value1; 
unsigned int value2; 
unsigned int value3; 

value2 += (value1%1000) << 16; 
unsigned long result = ((value2/1000) << 16) | ((value3 + ((value2 % 1000) << 16))/1000); 
+1

你需要查找“多精度运算”左右。是的,有办法做到这一点。例如,完整的通用解决方案([GMP](https://gmplib.org/) - GNU Multi-Precision)可能会矫枉过正,但您最终会使用函数来完成这项工作,而且它们不会不重要的。 –

+0

unsigned int result =(T1High << 22 | T1Low >> 10) – KonstantinL

+0

http://stackoverflow.com/questions/5284898/implement-division-with-bit-wise-operator – aicastell

回答

2

我会做一个分工基地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; 

当然,您也可以将其制定为循环,但我怀疑它是否值得。这种方法尽可能精确。缺点是,它需要三个分区和两个乘法,如果您的计算资源紧张,可能会导致性能问题。

+0

我试过这种方法。我尝试了最大数量9 999 999 000,从中我想要9 999 999.所以我将数字分成3 16位(0xE018,0x540B,0x0002)。我得到0x00,0x98,0x7f – Daniel

+0

@丹尼尔似乎你使用的是错误的字节顺序:'0x0002'应该是'value1'和'0xe018'应该是'value3' – cmaster

+0

@丹尼尔只要想一想你会如何用纸和笔划分。 – cmaster

3

数学上讲,T1High << 32 | T1Low相当于

T1High * 2**32 + T1Low 

和总和的dVision可以与分割的总和来代替它可以使我们以下列公式计算:

((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) 
+0

不幸的是我不能松开精度,我只需要删除三个零:) – Daniel

2

但我想用1000除以48位值,并将其保存到一个32位

您的规范是没有意义的。 2^48 = 2.81e142.81e14/1000 = 2.81e11。一个32位的数字可以容纳4.29e9,所以除以1000不能解决任何问题 - 数字不适合。

话虽这么说,不要被1000除以1024这是相同的10点。或者,如果你愿意,放弃至少10位显著为右移数除以。

+0

我知道它听起来很奇怪,但原因很简单: 仪表以千瓦小时为单位,但数值以瓦特给出。最大值是9 999 999,这足以保存在32位。但从米我会得到9 999 999 000 ... 所以我需要在最后削减3个零... – Daniel

相关问题