![](/img/trans.png)
[英]How To Convert QBytearray BCD to Decimal QString Representation?
[英]How best to implement BCD as an exercise?
我是學習C ++的初學者(自學)程序員,最近我決定實現一個二進制編碼的十進制(BCD)類作為練習,因此我可以在Euler項目上處理非常大的數字。 我想從頭開始正確地盡可能地做到這一點。
我開始使用一個整數數組,其中輸入數字的每個數字都保存為一個單獨的整數。 我知道每個BCD數字只能用4位編碼,因此我認為為此使用一個完整的int有點過分。 我現在正在使用bitset <4>的數組。
編輯:這樣做的主要原因是作為練習-我不想使用GMP之類的庫,因為整個觀點都是我自己寫的。 有沒有一種方法可以確保每個十進制數字僅使用4位?
請注意,使用bitset<4>
數組將需要與long數組相同的空間。 通常通過將字大小的整數數組作為位的后備存儲來實現位集,以便按位操作可以使用按位字操作,而不是字節操作,因此一次可以完成更多操作。
另外,我質疑你的動機。 在系統之間發送BCD時,通常將BCD用作數字字符串的打包表示。 通常,算術實際上沒有任何關系。 您真正想要的是一個任意大小的整數算術庫,例如GMP 。
是否也在使用類似此類的庫類?
我將它與一系列整數進行基准比較,以查看哪種表現更好。 如果bitset <4>的數組更快,那么不算過分。 一點點幫助解決一些體育問題
您會認為它作弊嗎?
一點都不。
有一個更好的方法嗎?
就像格雷格·羅傑斯(Greg Rogers)所建議的那樣,任意精度庫可能是一個更好的選擇,除非您只是想從自己的基礎上學習。 從這兩種方法中都有一些要學習的東西(使用庫還是編寫庫)。 我很懶,所以我通常使用Python。
就像格雷格·羅傑斯(Greg Rogers)所說的那樣,使用位集可能不會比int節省任何空間,並且實際上不會提供任何其他好處。 我可能會改用向量。 它的大小是所需大小的兩倍,但是您可以為每個數字建立更簡單,更快速的索引。
如果要使用打包的BCD,則可以編寫自定義索引功能,並在每個字節中存儲兩位數字。
- 是否也在使用類似此類的庫類?
- 您會認為它作弊嗎?
- 有一個更好的方法嗎?
1&2:不是真的
3:每個字節有8位,您可以在每個未簽名的char中存儲2個BCD。
通常,位操作是在整數的上下文中應用的,因此從性能方面來看,沒有真正的理由去使用位。
如果您想通過一點方法來獲得經驗,那么這可能會有所幫助
#include <stdio.h>
int main
(
void
)
{
typedef struct
{
unsigned int value:4;
} Nibble;
Nibble nibble;
for (nibble.value = 0; nibble.value < 20; nibble.value++)
{
printf("nibble.value is %d\n", nibble.value);
}
return 0;
}
要點是在struct內部,您正在創建一個短整數,一個4位寬的整數。 實際情況下,它實際上仍然是整數,但是對於您的預期用途,它看起來像是4位整數。
for循環清楚地表明了這一點,它實際上是一個無限循環 。 當半字節值達到16時,該值實際上為零,因為只有4位可以使用。 結果, nibble.value <20永遠不會為真。
如果您查看《 K&R白皮書》,其中一項便箋是這樣的位操作不可移植的事實,因此,如果您想將程序移植到另一個平台上,可能會或可能不會。
玩得開心。
您正在嘗試獲取以10為基的表示形式(即數組的每個單元格中的十進制數字)。 這樣就浪費了空間(每個數字一個整數)或時間(每個dgit 4位,但打包/拆包的開銷)。
例如,為什么不嘗試使用base-256並使用字節數組呢? 甚至是基數為2 ^ 32的整數數組? 這些操作的實現方式與10級基礎相同。 唯一不同的是將數字轉換為人類可讀的字符串。
它可能是這樣工作的:假設以256為基,每個“數字”都有256個可能的值,因此數字0-255都是單數字值。 大於256的字符寫為1:0(我將使用冒號分隔“數字”,我們不能使用像base-16那樣的字母),base-10的類比是9之后的數字,等於10。1030類似。 -10)= 4 * 256 + 6 = 4:6(以256為基)。 1020(base-10)= 3 * 256 + 252 = 3:252(base-256)是base-256中的兩位數。
現在假設我們將數字放在字節數組中,最低有效數字在前:
unsigned short digits1[] = { 212, 121 }; // 121 * 256 + 212 = 31188
int len1 = 2;
unsigned short digits2[] = { 202, 20 }; // 20 * 256 + 202 = 5322
int len2 = 2;
然后添加將如下所示(警告:前面的記事本代碼可能已損壞):
unsigned short resultdigits[enough length] = { 0 };
int len = len1 > len2 ? len1 : len2; // max of the lengths
int carry = 0;
int i;
for (i = 0; i < len; i++) {
int leftdigit = i < len1 ? digits1[i] : 0;
int rightdigit = i < len2 ? digits2[i] : 0;
int sum = leftdigit + rightdigit + carry;
if (sum > 255) {
carry = 1;
sum -= 256;
} else {
carry = 0;
}
resultdigits[i] = sum;
}
if (carry > 0) {
resultdigits[i] = carry;
}
在第一次迭代中,它應該像這樣:
在第二次迭代中:
因此,最后結果為digits [] = {158,142},即142:158(base-256)= 142 * 256 + 158 = 36510(base-10),正好是31188 + 5322
請注意,將這個數字轉換為人類可讀的格式絕非易事-它需要乘以10或256的乘法和除法,如果沒有適當的研究,我將無法作為示例提供代碼。 這樣做的好處是可以真正有效地執行“加”,“減”和“乘”運算,並且在計算的開始和結束之后僅進行一次與以10為底的大量轉換。
說了這么多,就我個人而言,我將使用以10為基數的字節數組,而不關心內存丟失。 這將需要將常數255和256分別調整為9和10。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.