19

有没有一种简单的方法来确定 GMP 整数的位数?我知道您可以通过日志确定它,但我想知道库中是否有一些我缺少的东西。我在手册中找到的唯一内容是:

_mp_size 肢体的数量,或表示负整数时的负数。零由 _mp_size 设置为零表示,在这种情况下,_mp_d 数据未被使用。

但我的印象与我正在寻找的完全不同。

IE

124839 = 6 位数。

4

1 回答 1

17

您可以使用size_t mpz_sizeinbase (mpz_t op, int base)获取字符数以将数字输出为特定基数的字符串。

size_t mpz_sizeinbase (mpz_t op, int base)

返回以给定基数中的位数测量的 op 的大小。base 可以在 2 到 62 之间变化。 op 的符号被忽略,只使用绝对值。结果将是精确的或 1 太大。如果 base 是 2 的幂,则结果总是准确的。如果 op 为零,则返回值始终为 1。

此函数可用于确定将 op 转换为字符串时所需的空间。正确的分配量通常比 mpz_sizeinbase 返回的值多两个,一个用于减号,一个用于空终止符。

所以类似于:

size_t sz = mpz_sizeinbase (myNum, 10);

应该是一个好的开始。

如果您想要确切的大小,您可以使用该值创建一个足够大的缓冲区,将值输出该缓冲区,然后执行 astrlen以获得更准确的大小,例如:

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);
}

请注意,这不是最有效的方法,因为每次您想要查找长度时它都会分配一个缓冲区,并且如果分配失败,它默认为最安全的大小,这可能比必要的大一倍。

另一种可能的方法是使用更安全的snprintf选项,因为它返回被写入的字节数,并防止缓冲区溢出:

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

我没有专门测试过,但这是我以前用于“常规”C 样式打印的技巧。

请注意,这两种“精确尺寸”解决方案都在前面包含一个可选标志。如果您想真正计算数字而不是字符,则应对此进行调整(例如,如果数字小于零,则从大小中减去 1)。

于 2011-02-20T16:25:59.020 回答