[英]Get bits from number string
如果我有一個數字字符串(字符數組),一個數字就是一個字符,導致四位數字的空間是 5 個字節,包括空終止。
unsigned char num[] ="1024";
printf("%d", sizeof(num)); // 5
但是,1024 可以寫成
unsigned char binaryNum[2];
binaryNum[0] = 0b00000100;
binaryNum[1] = 0b00000000;
如何有效地進行字符串到二進制的轉換? 在我的程序中,我將使用 ≈30 位數字,因此空間增益會很大。 我的目標是創建要通過 UDP/TCP 發送的數據包。
我不希望為此任務使用庫,因為代碼可以占用的可用空間很小。
編輯:感謝您的快速回復。
char num = 0b0000 0100 // "4"
--------------------------
char num = 0b0001 1000 // "24"
-----------------------------
char num[2];
num[0] = 0b00000100;
num[1] = 0b00000000;
// num now contains 1024
我需要 ≈ 10 個字節來包含我的二進制形式的數字。 所以,如果我按照建議從后面開始一個一個地解析數字,那將如何建立最終的大二進制數?
通常,將字符串表示形式的數字轉換為十進制很容易,因為每個字符都可以單獨解析。 例如,要將"1024"
轉換為1024
您只需查看'4'
,將其轉換為4
,乘以10
,然后轉換2
並添加它,乘以10
,依此類推,直到您解析了整個字符串。
對於二進制它不是那么容易,例如您可以將4
轉換為100
和2
到010
但42
不是100 010
或110
或類似的東西。 因此,最好的辦法是將整個事物轉換為數字,然后使用數學運算(位移等)將該數字轉換為二進制。 這對於適合其中一種 C++ 數字類型的數字可以正常工作,但是如果您想處理任意大的數字,您將需要一個BigInteger
類,這對您來說似乎是一個問題,因為代碼必須很小。
從您的問題中,我認為您想壓縮字符串表示以便通過網絡傳輸數字,因此我提供的解決方案不會嚴格轉換為二進制,但仍會使用比字符串表示更少的字節並且易於用。 它基於這樣一個事實:您可以將數字0..9
存儲在 4 位中,因此您可以在一個字節中容納其中兩個數字。 因此,您可以在n/2
字節中存儲n
位數字。 該算法可能如下:
'4'
'0'
得到4
(即一個值為 4 的 int)。0
digits[0] = (4 << 4) + 0
。digits[1] = (2 << 4) + 1
。您在內存中的表示現在看起來像
4 0 2 1
0100 0000 0010 0001
digits[0] digits[1]
IE
digits = { 64, 33 }
這不是 1024 的二進制表示,但它更短,它允許您通過反轉算法輕松恢復原始數字。
您甚至還有 5 個不用於存儲數字的值(即所有大於1010
),您可以將它們用於其他內容,例如存儲符號、小數點、字節順序或數字結束分隔符)。
如果您選擇使用它,我相信您將能夠實現它。
如果我正確理解你的問題,你會想要這樣做:
string
表示形式轉換為integer
。integer
轉換為binary
表示。對於第 1 步:
char
減去'0'
10^n
(取決於位置)並添加到總和。 對於第 2 步(對於int x
),通常:
x%2
為您提供最低有效位 (LSB)。x /= 2
“刪除” LSB。 例如,取x = 6
。
x%2 = 0
(LSB), x /= 2
-> x becomes 3
x%2 = 1
, x /= 2
-> x becomes 1
x%2 = 1
(MSB), x /= 2
-> x becomes 0
。 所以我們看到(6)decimal == (110)bin
。
關於實現(對於N=2
,其中N
是最大bytes
數):
int x = 1024;
int n=-1, p=0, p_=0, i=0, ex=1; //you can use smaller types of int for this if you are strict on memory usage
unsigned char num[N] = {0};
for (p=0; p<(N*8); p++,p_++) {
if (p%8 == 0) { n++; p_=0; } //for every 8bits, 1) store the new result in the next element in the array. 2) reset the placing (start at 2^0 again).
for (i=0; i<p_; i++) ex *= 2; //ex = pow(2,p_); without using math.h library
num[n] += ex * (x%2); //add (2^p_ x LSB) to num[n]
x /= 2; // "remove" the last bit to check for the next.
ex = 1; // reset the exponent
}
我們可以檢查x = 1024
的結果:
for (i=0; i<N; i++)
printf("num[%d] = %d\n", i, num[i]); //num[0] = 0 (0b00000000), num[1] = 4 (0b00000100)
將最多 30 位十進制數(以字符串表示)轉換為一系列字節,有效地以 256 為基數表示,最多需要 13 個字節。 (30/log10(256) 的上限)
簡單算法
dest = 0
for each digit of the string (starting with most significant)
dest *= 10
dest += digit
作為 C 代碼
#define STR_DEC_TO_BIN_N 13
unsigned char *str_dec_to_bin(unsigned char dest[STR_DEC_TO_BIN_N], const char *src) {
// dest[] = 0
memset(dest, 0, STR_DEC_TO_BIN_N);
// for each digit ...
while (isdigit((unsigned char) *src)) {
// dest[] = 10*dest[] + *src
// with dest[0] as the most significant digit
int sum = *src - '0';
for (int i = STR_DEC_TO_BIN_N - 1; i >= 0; i--) {
sum += dest[i]*10;
dest[i] = sum % 256;
sum /= 256;
}
// If sum is non-zero, it means dest[] overflowed
if (sum) {
return NULL;
}
}
// If stopped on something other than the null character ....
if (*src) {
return NULL;
}
return dest;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.