Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

How to handle display 128 bit integer (signed and unsigned)

2,127 views
Skip to first unread message

emitrax

unread,
Jun 9, 2009, 7:11:33 PM6/9/09
to
Hi,

I'm trying to understand how I can deal with big integers, such as 128
bit big.
From 8 up to 64 bit, I have not problem, as stdint.h provides data
types for all
of those, and so the conversion character of printf. But as for
integers 128bit long,
I just have not idea about how to display them.

I've managed to figure out how to generate and store the data (see the
following
typedef), but as I said, I don't know how to display them with printf,
or analogous call.

typedef struct {
uint64_t low;
uint64_t high;
} uint128_t;

typedef struct {
int64_t low;
int64_t high;
} int128_t;

Any help would be appreciated about how to display the data. I have
not need to process the data (sum, multiplication etc..).

Thanks,
S.
--
comp.lang.c.moderated - moderation address: cl...@plethora.net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry.

Pavel Borzenkov

unread,
Jun 10, 2009, 9:35:15 PM6/10/09
to
comp.lang.c.moderated
User-Agent: Unison/1.8.1

Hi. If you use Linux with glibc 2.10 you can define printf hooks for
your own data types.
Refer to the Ulrich Drepper livejournal for more details
(http://udrepper.livejournal.com/20948.html). Specifically, the 'printf
hooks' section.

-
Pavel

Dag-Erling Smørgrav

unread,
Jun 10, 2009, 9:35:00 PM6/10/09
to
emitrax <emi...@gmail.com> writes:
> I'm trying to understand how I can deal with big integers, such as 128
> bit big. [...]

>
> typedef struct {
> uint64_t low;
> uint64_t high;
> } uint128_t;

This is one of several possible solutions. A common one (making several
assumptions about the exact representation your particular system uses)
is this:

typedef union {
uint64_t u64[2];
uint32_t u32[4];
uint16_t u16[8];
uint8_t u8[16];
} uint128_t;

This can be awkward on big-endian systems, as the arrays will be
numbered in the "wrong" order (the most-significant element will be
element 0)

> Any help would be appreciated about how to display the data.

You can use a chain of integer divisions to extract digits from right to
left. The details are left as an exercise to the reader.

Alternatively, you can use a multiple-precision arithmetic library such
as libgmp, even if you don't need to perform arithmetic operations; it
will have function for converting numbers to strings.

DES
--
Dag-Erling Smørgrav - d...@des.no

Barry Schwarz

unread,
Jun 10, 2009, 9:34:11 PM6/10/09
to
On Tue, 9 Jun 2009 18:11:33 -0500 (CDT), emitrax <emi...@gmail.com>
wrote:

>Hi,
>
>I'm trying to understand how I can deal with big integers, such as 128
>bit big.
>From 8 up to 64 bit, I have not problem, as stdint.h provides data
>types for all
>of those, and so the conversion character of printf. But as for
>integers 128bit long,
>I just have not idea about how to display them.
>
>I've managed to figure out how to generate and store the data (see the
>following
>typedef), but as I said, I don't know how to display them with printf,
>or analogous call.
>
>typedef struct {
> uint64_t low;
> uint64_t high;
>} uint128_t;
>
>typedef struct {
> int64_t low;
> int64_t high;
>} int128_t;

Even though the structure represents a signed value, you may want to
use unsigned types for the members simply because it is possible
(likely?) that the sign bit in low can be set for a positive value
such as values between pow(2,63) and pow(2,64)-1 and for half the
values greater than pow(2,64).

I assume you mean print in decimal since printing in hex is trivial.
Obviously printf won't support this directly. One possibility is to
create an sprintf work-alike that will take your object and populate a
string with the corresponding decimal digits.

pow(2,10) is slightly more that pow(10,3) so pow(2,128) should be
around pow(10,40). Assuming you have a subtract and a compare
function, one approach (untested) is

char* sprintf128(int128_t value){
static int128_t decimal[41] = {...}; /*The initialization values
correspond to pow(2,40), pow(2,39), ..., pow(2,0) */
static char output(41);
int i, j, k;
memset(output, '0', sizeof output);
for (i = 0, j = 0; j < 41; j++, i++){
while (compare128(value, decimal[j]) >= 0){
output[i]++;
value = sub128(value, decimal[j]);
}
}
output[i] = '\0'
return output;
}

You could use this in any of the standard printf function like
printf("%s\n", sprintf128(&my_struct128));

You could also decide to adjust the return value to suppress leading
zeros. Inserting commas and handling the sign are left as an
exercise.

Unless you are counting Turkish lire, what are doing that needs a
number this big?

You might also want to google for big number libraries since there are
others whose internal representation simplifies printing.

--
Remove del for email

emitrax

unread,
Jun 12, 2009, 12:45:18 PM6/12/09
to
Hi,

first of all thanks for the answers! I think I understand
how to deal with it now.

I was actually looking for a ready-to-use solution, but the
conversion to string makes actually sense.

I'll be back with a working solution for opinions and feedback.

Thanks again!

Regards,
Salvatore

0 new messages