2017-04-06 95 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

相關問題