不同基数中大整数位数的上限

时间:2015-02-28 10:45:45

标签: c floating-point floating-accuracy floating-point-precision

我想从字符串表示创建一个大整数,为了有效地做到这一点,我需要一个目标库中数字位数的上限,以避免重新分配内存。

示例:

640 bit号码在base 2中有640位数字,但base 2^64只有十位数,所以我必须分配十个64 bit整数来保存结果。< / p>

我目前使用的功能是:

int get_num_digits_in_different_base(int n_digits, double src_base, double dst_base){
    return ceil(n_digits*log(src_base)/log(dst_base));
}

src_base位于{2, ..., 10 + 26}dst_base位于{2^8, 2^16, 2^32, 2^64}的位置。

我不确定结果是否总是会被正确舍入。 log2会更容易推理,但我读到旧版本的Microsoft Visual C ++不支持该功能。它可以像log2(x) = log(x)/log(2)一样模拟,但现在我回到了我开始的地方。

GMP可能实现了进行碱基转换的功能,但我可能无法阅读来源,否则我可能会得到GPL癌症,所以我不能这样做。

2 个答案:

答案 0 :(得分:0)

我认为速度是一个值得关注的问题,否则你可以尝试基于浮点数的估算并调整它是否太小了。在这种情况下,人们可以牺牲速度估计的紧张程度。

在下文中,让dst_base为2 ^ w src_base b n_digits ñ

k(b,w) = max { j | b ^ j &lt; 2 ^ 瓦特}。这代表 b 的最大功率,保证适合 w 范围内的二进制(非负)整数。由于源和目标库的数量相对较少,这些值可以预先计算并在表格中查找,但数学上 k(b,w)= [ w log 2 / log b ](其中[。]表示整数部分。)

对于给定的 n ,让 m = ceil( n / k b,w ))。然后,保存小于 b ^ n 的数字所需的最大dst_base位数为:

ceil(log( b ^ n -1)/ log(2 ^ w ))≤ceil(log( b ^ n )/ log(2 ^ w )) ≤ceil( m .log( b ^ k b w ) )/ log(2 ^ w ))≤m。

简而言之,如果您预先计算 k(b,w)值,则可以通过将 n 除以快速得到上限(不紧!) k ,四舍五入。

答案 1 :(得分:0)

在这种情况下,我不确定浮点舍入,但是仅使用整数来实现它相对容易,因为log2是经典的位操作模式,并且整数除法可以很容易地舍入。以下代码与您的代码相同,但使用整数:

// Returns log2(x) rounded up using bit manipulation (not most efficient way)
unsigned int log2(unsigned int x)
{
    unsigned int y = 0;
    --x;
    while (x) {
        y++;
        x >>= 1;
    }
    return y;
}

// Returns ceil(a/b) using integer division
unsigned int roundup(unsigned int a, unsigned int b)
{
    return (a + b - 1) / b;
}

unsigned int get_num_digits_in_different_base(unsigned int n_digits, unsigned int src_base, unsigned int log2_dst_base)
{
    return roundup(n_digits * log2(src_base), log2_dst_base);
}

请注意:

  • 与您的相比,此功能会返回不同的结果!但是,在我看的每一个案例中,两者都是正确的(较小的值更准确,但你的要求只是一个上限)。
  • 我写的整数版本收到log2_dst_base而不是dst_base,以避免2^64溢出。
  • 使用查找表可以提高
  • log2的效率。
  • 我使用unsigned int代替int