Mathieu Malaterre wrote:

> Hello,

>

> I have the following problem. I need to convert a unsigned char[6]

> array into a string using only number (0-9) and '.'. The goal being
to

> stored it on the minimal number of bytes.

>

> The first approach is a representation ala IP address:

> 255.255.255.255.255.255 therefore it takes 6*3+5 = 23 bytes. I can
even

> get rid of the dot since the lenght is fixed. So I can go down to 3*6
=

> 18 bytes.
Actually, char's could also be 16 bits, in which case you'd need

6*5 chars. In general, they're CHAR_BIT wide.

> I relized that this also can be represented as a number 256^6 =

> 281474976710656 which fits only on 15 bytes . Unfortunately this
number

> is too big for usual c types. I tried to reimplement the
multiplication

> with strings, but I gave up quickly.
Don't. It's the correct way. Remember, you don't have to store the

number

itself. You're generating a string.

Basically, what you need to do is to write a class:

class Num {

uchar data[6];

public:

Num ( ? );// I don't know how you get those chars

char div10();

};

Num::div10() should return Num%10 and modify Num::data[6].

With that, you can do a recursive div10 until div10 returns 0.

Now, how do you implement (uchar data[6])%10? Simple.

The main rule is (A+B)%X = ((A%X)+(B%X))%X. This reduces

the size of the numbers, and fixes overflows.

You basically want(data[i]<<CHAR_BIT*i)%10, which therefore

is equal to ((data[i]<<CHAR_BIT*i) %10)%10. The advantage of

this approach is that ((data[i]<<CHAR_BIT*i) %10) will be at

most 6*9 = 54.

Again, you need to do a similar reduction to calculate

(data[i]<<CHAR_BIT*i) %10. This is equal to

(data[i]*(1<<CHAR_BIT*i)) % 10, and we have a similar rule

(A * B)%X = ((A%X) * (B%X))%X . You get the idea, do the %

operation early so you know each term stays small.

BTW, you can get the string even shorter if you use the '.'

as the eleventh digit. In that case, 255 = 2*121+1*11+2 =

"212" base 11, and 242 is "1.."

Regards,

Michiel Salters