Reputation: 746
I have a hex number which consist of 5 bytes: 0xEEDDCCBBAA. This number is stored in an array: [0xEE 0xDD, 0xCC, 0xBB, 0xAA]. I want to convert it to 10base decimal number and represent it as a C-type string: "1025923398570". (0xEEDDCCBBAA is equal to 1,025,923,398,570)
One problem is my system only supports max. 32-bits type variable, so I cannot have a single variable to store this number or perform any type of operation larger than 32-bits. For example I cannot do:
unsigned long long val = 0xeeddccbbaa;
unsigned char buf[50];
sprintf(buf, "%d", val);
Thank you very much.
Edit: As my question seems confusing so I wrote it again.
Upvotes: 1
Views: 1373
Reputation:
The real challenge here is the conversion to base 10
, using 32 bits arithmetic only.
Let your 64 bits number be N = M.2^32 + L
, and use the decomposition X = 10 (X/10) + (X%10) = 10 Xq + Xr
.
Then,
N = (10.Mq + Mr)(10.429496729 + 6) + (10.Lq + Lr) = 100.429496729.Mq + 10.6.Mq + 10.429496729.Mr + 6.Mr + 10.Lq + Lr.
From this we derive the unit digit
Nr = N%10 = (6.Mr + Lr) % 10,
and the quotient
Nq = N/10 = 10.429496729.Mq + 6.Mq + 429496729.Mr + Lq + (6.Mr + Lr) / 10.
In the latter expression, the first two terms are just Mq.2^32
, so you divide the most significant doubleword by 10
. The next term will fit in 32 bits as Mr
is at most 9
and 429496729.9
is less than 2^32
. I don't think that a carry from the LSD to the MSD can arise, but this should be double-checked.
You can continue this division process to extract the next digits, until the MSD becomes 0 (then continue with the LSD alone).
In your example case
M = 0xEE = 238 = 10 * 23 + 8, N = 0xDDCCBBAA = 3721182122 = 10 * 372118212 + 2
The unit digit is Nr = (6 * 8 + 2) % 10 = 0
.
The quotient by 10
is
M' = 238 / 10 = 23, L' = 429496729 * 8 + 372118212 + (6 * 8 + 2) / 10 = 3808092049.
(As you can check, 23 * 2^32 + 3808092049= 102592339857
.)
The next digit is N'r = (6 * 3 + 9) % 10 = 7
.
The quotient by 10
is
M" = 23 / 10 = 2, L" = 429496729 * 3 + 380809204 + (6 * 3 + 9) / 10 = 1669299393.
(As you can check, 2 * 2^32 + 1669299393 = 10259233985
.)
The next digit is N"r = (6 * 2 + 3) % 10 = 5
.
The quotient by 10
is
M"' = 2 / 10 = 0, L"' = 429496729 * 2 + 166929939 + (6 * 2 + 3) / 10 = 1025923398.
As M"' = 0
, you can now continue the conversion in pure 32 bits.
Upvotes: 0
Reputation: 153498
Could create a generic routine to handle any size byte array.
#include <string.h>
char *convert_10base_decimal_number(char *dest, size_t dsize, unsigned char *a,
size_t asize) {
if (dsize == 0)
return NULL;
char *d = dest + dsize - 1;
*d = '\0';
size_t ai = 0;
do {
// mod 10
unsigned carry = 0;
for (size_t i = ai; i < asize; i++) {
carry = carry * 256 + a[i];
a[i] = carry / 10;
carry %= 10;
}
if (d == dest)
return NULL;
d--;
*d = carry + '0';
if (a[ai] == 0)
ai++;
} while (ai < asize);
memmove(dest, d, dsize - (d - dest));
return (dest);
}
int main(void) {
unsigned char a[] = { 0xEE, 0xDD, 0xCC, 0xBB, 0xAA };
char buf[50];
puts(convert_10base_decimal_number(buf, sizeof buf, a, sizeof a));
// 1025923398570
return 0;
}
This method does consume the array a
.
Upvotes: 1
Reputation: 3029
char a[5] = {0xEE, 0xDD, 0xCC, 0xBB, 0xAA};
// @Shmoopy's piece of code
int x = a[0] | (a[1] << 8) | (a[2] << 16) || (a[3] << 24);
int y = a[4];
// making long long from x and y, where y is the mo;
long long z = (long long)y << 32 | x;
// conversion of long long to string with base 10 (2^64 has max 19 decimal digits)
char str[20] = {};
lltoa(z, str, 10);
printf("The number is %s.\n", str);
Upvotes: 0
Reputation: 5534
long x,y;
x = a[0] | (a[1] << 8) | (a[2] << 16) || (a[3] << 24)
y = a[4]
So x
is 0xEEDDCCBB
and y
is 0xAA
You can use sprintf to convert x to a string and then concatenate it to y.
Upvotes: 0