Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Number of digits of GMP integer

Is there an easy way to determine the number of digits a GMP integer has? I know you can determine it through a log, but I was wondering if there was something built into the library that I'm missing. The only thing I've found in the manual is:

_mp_size The number of limbs, or the negative of that when representing a negative integer. Zero is represented by _mp_size set to zero, in which case the _mp_d data is unused.

But I'm under the impression that is quite different than what I'm looking for.

i.e

124839 = 6 digits.

like image 913
Darkenor Avatar asked Feb 20 '11 16:02

Darkenor


People also ask

What is Mpz in GMP?

GMP: Multi-precision Arithmetic. 1. mpz: Multi-precision Integers. 2. mpq: Multi-precision Rational Numbers.

What is Mpz_t?

mpz_t Class. Represents a multiple precision integer. Inheritance Hierarchy.


1 Answers

You can use size_t mpz_sizeinbase (mpz_t op, int base) to get the number of characters to output the number as a string in a specific base.

size_t mpz_sizeinbase (mpz_t op, int base)

Return the size of op measured in number of digits in the given base. base can vary from 2 to 62. The sign of op is ignored, just the absolute value is used. The result will be either exact or 1 too big. If base is a power of 2, the result is always exact. If op is zero the return value is always 1.

This function can be used to determine the space required when converting op to a string. The right amount of allocation is normally two more than the value returned by mpz_sizeinbase, one extra for a minus sign and one for the null-terminator.

So something along the lines of:

size_t sz = mpz_sizeinbase (myNum, 10);

should be a good start.

If you want the exact size, you can use that value to create a big enough buffer, output the value to that buffer, then do a strlen to get the more accurate size, something like:

size_t sz = mpz_sizeinbase (myNum, 10) + 1; // allow for sign
char *buff = malloc (sz + 1);               // allow for `\0`
if (buff != NULL) {
    gmp_sprintf (buff, "%Zd", myNum);
    sz = strlen (buff);
    free (buff);
}

Note that it's not the most efficient way since it allocates a buffer every time you want to find the length, and it defaults to the safest size if the allocation fails, which could be one larger than necessary.

Another possible way is to use the safer snprintf option, since that returns the number of bytes that would have been written, and prevents buffer overflow:

char oneChar;
int sz = gmp_snprintf (&oneChar, 1, "%Zd", myNum);

I haven't tested that specifically but it's a trick I've used for "regular" C-style printing before.

Note that both those "exact size" solutions include an optional sign at the front. If you want to truly count the digits rather then the characters, you should adjust for that (subtracting one from the size if the number is less than zero, for example).

like image 196
paxdiablo Avatar answered Oct 05 '22 20:10

paxdiablo