如果我有兩個打包的BCD格式的數字並想添加它們,是不是像這樣添加它們的好方法:將兩個數字轉換爲整數,執行正常的整數加法,然後轉換結果返回到BCD?使用整數的二進制編碼的十進制加法
1
A
回答
1
下面的C99代碼將打包的BCD操作數與存儲在uint32_t
中的八個BCD數字相加。通過選擇uint64_t
來處理16位BCD數字,此代碼很容易擴展到更寬的BCD操作數。由於這種方法依賴於位並行處理,因此對於窄分組BCD操作數可能效率不高。
在打包的BCD格式中,每個BCD數字佔用一個無符號整數操作數的一個半字節(4位組)。如果以半字節爲單位的加法結果大於9,我們希望進入下一個更高的半字節。如果我們使用常規整數加法來添加兩個打包的BCD操作數,當半字節總和大於9時,所需的半字節進位不會發生,但是< 16.爲了解決這個問題,我們可以爲每個半字節和加上一個額外的6。
我們可以發現這個半字節攜帶如下:兩個整數x
,y
的按位總和爲x^y
。在常規整數相加期間,在下一個較低位位置有進位的任何位位置,x^y
和x + y
中的位將有所不同。所以我們可以找到帶進位的位作爲(x^y)^(x + y)
。我們對位4,8,...,32的第3,7,...,31位是有意義的。
如果存在一個小問題因爲uint32_t
操作數僅保存32位,所以從位31到位32執行。如果我們發現兩個無符號整數的和小於任何一個加數,我們可以檢測到這一點。操作7位操作數而不是8位操作數時,可以省略處理從位31執行的三個操作。
/* Add two packed BCD operands, where each uint32_t holds 8 BCD digits */
uint32_t bcd_add (uint32_t x, uint32_t y)
{
uint32_t t0, t1;
t0 = x + 0x66666666; // force nibble carry when BCD digit > 9
t1 = x^y; // bit-wise sum
t0 = t0 + y; // addition with nibble carry
t1 = t1^t0; // (x^y)^(x + y)
t0 = t0 < y; // capture carry-out from bit 31
t1 = (t1 >> 1) | (t0 << 31); // nibble carry-outs in bits 3, 7, ..., 31
t0 = t1 & 0x88888888; // extract nibble carry-outs
t1 = t0 >> 2; // 8 - (8 >> 2) = 6
return x + y + (t0 - t1); // add 6 to any digit with nibble carry-out
}
Knuth的,TAOCP Vol.4A第1部分,提供在應答一個優越的解決方案(需要更少的操作),以從部分7.1.3行使100。該變體特別適合處理器體系結構,其指令可評估三個參數的任何邏輯函數,例如現代NVIDIA GPU的LOP3
指令。
uint32_t median (uint32_t x, uint32_t y, uint32_t z)
{
return (x & (y | z)) | (y & z);
}
uint32_t bcd_add_knuth (uint32_t x, uint32_t y)
{
uint32_t z, u, t;
z = y + 0x66666666;
u = x + z;
t = median (~x, ~z, u) & 0x88888888;
return u - t + (t >> 2);
}
相關問題
- 1. 十進制數的二進制補碼
- 2. 將二進制編碼的十進制(BCD)解碼爲無符號整數
- 3. 有符號整數到二進制補碼十六進制
- 4. 十進制到二進制(二進制)
- 5. 將帶符號的十進制轉換爲使用二進制補碼編碼的十六進制
- 6. C中的BCD(二進制編碼的十進制)
- 7. 十進制到二進制代碼
- 8. 將整數轉換爲二進制/十進制的MIPS函數?
- 9. 十進制/整數乘法
- 10. 如何將數字(十進制)轉換爲二進制(二進制)數字和從二進制到十進制?
- 11. 二進制到十進制
- 12. 十進制到二進制Java方法
- 13. 十六進制,八進制,二進制到十進制(C++)
- 14. 二進制,八進制,十六進制到十進制程序
- 15. 使用波紋管算法將二進制整數轉換爲十進制
- 16. C++中整數的十進制,八進制和十六進制表示法
- 17. 獲得負數的二進制補碼的十六進制
- 18. C#編碼:十六進制到十進制&字符編碼
- 19. 對可變位二進制塊中的十進制值進行編碼/解碼
- 20. 二進制十進制負數位集
- 21. 十進制和二進制數處理
- 22. 十進制素數到二進制
- 23. 二進制數據的十六進制編碼的目的是什麼?
- 24. Python中,如何解碼二進制編碼的十進制(BCD)的二進制字段的
- 25. Python中十六進制數的二進制補碼
- 26. 二進制到十進制和十進制到二進制轉換器
- 27. 如何使用C將二進制整數作爲十六進制寫入二進制文件中使用C
- 28. 從十六進制到十進制,二進制到十進制和八進制到十進制程序C++
- 29. 二進制到十進制的公式
- 30. 將十進制數轉換爲二進制/十六進制/八進制符號
不知道爲什麼有接近的投票,這個問題對我來說似乎很好。有許多方法可以使用比特操作等來逐字添加多位BCD操作數。通常,這種方法往往比使用雙轉換路由更快。您的操作數組成了多少個BCD數字。我可能有一些C代碼來演示無轉換方法。 – njuffa
當然。有很多可能性(因此選票很近),但是如果您確信可以使其發揮作用,那麼爲什麼不呢? – usr2564301
@njuffa這是打包BCD,2位數字(這是包裝在一個8位'uint8_t'。我的一般問題是,當我不做雙重轉換,我如何檢查我的第一個或第二個數字是超過九,如果我想添加兩個數字,並且在添加之後他們超過了99,或者第一個數字超過了9,或者第二個數字超過了9,我怎麼檢查它?我知道我的問題很混亂, t知道如何描述它 – bingo157