473,382 Members | 1,369 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,382 software developers and data experts.

unsigned char [6] numerical representation

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.

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. I then try the union approach:

union { unsigned char s[6]; unsigned int i[2]; } dual;

dual.s = {0, 0, 0, 0, 0, 0};
char s[15];
std::copy( dual.i[0], dual.i[2], s);

but I am not sure how to do copy the unsigned int into a string ?

Thanks for any advice (in particular regarding the bytes ordering).

Thanks
Mathieu

Jul 22 '05 #1
5 3964
"Mathieu Malaterre" <mm**********@Mnycap.rr.com> wrote...
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.
What does 'unsigned char[6]' represent? Is that a 6-byte (48-bit)
integer number (up to 2^48-1)? Or is that something else? Converting
is a common task, but how to interpret those 6 bytes? What limits are
there imposed on their values? Or are those limits natural (0..255)?
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.

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 am not certain what you consider "usual", but nowadays you can have
an integer of 64 bits, should be enough.
I tried to reimplement the multiplication with strings, but I gave up
quickly. I then try the union approach:

union { unsigned char s[6]; unsigned int i[2]; } dual;

dual.s = {0, 0, 0, 0, 0, 0};
char s[15];
std::copy( dual.i[0], dual.i[2], s);

but I am not sure how to do copy the unsigned int into a string ?

Thanks for any advice (in particular regarding the bytes ordering).


If you want to treat those six bytes as one big integer (48 bits, no
sign), then you have to perform arithmetic operations to find out those
digits. Essentially, you need to find all remainders while dividing
your 48-bit number by 10.

Of course, the simplest thing would be using a compiler-specific 64-bit
integer, for which arithmetic operators are probably already implemented.
Or, find a library with "large integer" support and see what they offer.

Victor
Jul 22 '05 #2
Mathieu Malaterre wrote:
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.


[...]

I may have missed your point but, if the goal were to minimize storage
space and have the ability to read back the big number as a string, why
not encapsulate it in a class? The following (non-optimized) code could
give you an idea:

#include <string>
#include <sstream>
#include <iostream>

class IP
{
public:
IP(const std::string& ipString);
std::string asString();
private:
unsigned char mBytes[6];
};

IP::IP(const std::string& ipString)
{
std::istringstream iss(ipString);
std::istringstream snum;
unsigned int b;
std::string s;
for (unsigned int i = 0; i < 6; ++i)
{
std::getline(iss, s, '.');
snum.str(s);
snum >> b;
snum.clear();
mBytes[i] = b;
}
}

std::string IP::asString()
{
std::ostringstream oss;
unsigned int i;
for (i = 0; i < 5; ++i)
oss << static_cast<unsigned int>(mBytes[i]) << '.';
oss << static_cast<unsigned int>(mBytes[i]);
return oss.str();
}

int main()
{
IP ip("215.210.14.5.116.198");
std::cout << ip.asString();
}

Best regards,

--
Ney André de Mello Zunino
Jul 22 '05 #3

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

Jul 22 '05 #4

msalters wrote:
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. [ SNIP] I tried to reimplement themultiplication
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.


Ok, so I implemented it /after/ I posted it, and that's a bug.
Just try to print 1024, and you'll see why it fails. Stop when
all chars are 0 (simple test, really).

Furthermore, I found it a lot easier to just do a repeated divide
by N with carry. I.e.
carry = 0;
for(i)
{
extended = carry << CHAR_BIT + data[i]
data[i] = extended / N;
carry = extended % N
}
postcondition: carry is the last digit.

Regards,
Michiel Salters

Jul 22 '05 #5
Hello,

Thanks a lot all for your suggestions. But I always prefer the easy
way. Therefore here is what I do (works like a charm):
------------------------------------------------------------
#include <stdio.h>

#ifdef _MSC_VER
typedef unsigned __int64 uint64_t;
#else
#include <stdint.h>
#endif

int main()
{
union dual { unsigned char s[6]; uint64_t i; };
dual d = { 0 };

d.s[0] = 0;
d.s[1] = 0;
d.s[2] = 0;
d.s[3] = 0;
d.s[4] = 1;
d.s[5] = 0;

#ifdef _MSC_VER
printf("%015I64u\n", d.i);
#else

printf("%015llu\n", d.i);
#endif

return 0;
}
------------------------------------------------------------

Thanks anyway
Mathieu

msalters wrote:
msalters wrote:
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.
[ SNIP]
I tried to reimplement themultiplication
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.

Ok, so I implemented it /after/ I posted it, and that's a bug.
Just try to print 1024, and you'll see why it fails. Stop when
all chars are 0 (simple test, really).

Furthermore, I found it a lot easier to just do a repeated divide
by N with carry. I.e.
carry = 0;
for(i)
{
extended = carry << CHAR_BIT + data[i]
data[i] = extended / N;
carry = extended % N
}
postcondition: carry is the last digit.

Regards,
Michiel Salters


Jul 22 '05 #6

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

8
by: Rade | last post by:
Following a discussion on another thread here... I have tried to understand what is actually standardized in C++ regarding the representing of integers (signed and unsigned) and their conversions....
9
by: Magix | last post by:
Hi, char is 8 bit from -127 to 127 unsigned char is 8 bit from 0-255 from ASCII table, there is a list of char from 0-255. How char can be in negative value ? If I declare "char x", then can...
10
by: tinesan | last post by:
Hello fellow C programmers, I'm just learning to program with C, and I'm wondering what the difference between signed and unsigned char is. To me there seems to be no difference, and the...
16
by: TTroy | last post by:
Hello, I'm relatively new to C and have gone through more than 4 books on it. None mentioned anything about integral promotion, arithmetic conversion, value preserving and unsigned preserving. ...
5
by: Sathyaish | last post by:
When you say char in C, it internally means "an unsigned small integer with 1-byte memory", right? More importantly, the internal representation of char does not mean "int" as in...
4
by: ravinderthakur | last post by:
hi all experts, can anybody explain me the difference between the unsigned char and char in c/c++ langugage. specifically how does this affects the c library fucntion such as strcat,strtok...
2
by: ais523 | last post by:
I've been wondering about the compatibility of pointers to signed, unsigned and plain char, and it's not clear to me how interchangeable they are. Is the following portable? int main(int argc,...
14
by: moumita | last post by:
Hi All, I need to convert 4 bytes to an unsigned long. Suppose I have one array like unsigned char buf.I need to convert these 4 bytes into a single unsigned long. Is the following piece of code...
1
by: krishna81m | last post by:
I am a newbie and have been trying to understand conversion from double to int and then back to int using the following code was posted on the c++ google group. Could someone help me out with...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.