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

C 不同基中大整数位数的上限,c,floating-point,floating-accuracy,floating-point-precision,C,Floating Point,Floating Accuracy,Floating Point Precision,我想从字符串表示中创建一个大整数,为了有效地实现这一点,我需要一个目标基中位数的上限,以避免重新分配内存 例如: 一个640位的数字在基数2中有640位,但在基数2中只有10位^64,所以我必须分配10个64位整数来保存结果 我目前使用的功能是: int get_num_digits_in_different_base(int n_digits, double src_base, double dst_base){ return ceil(n_digits*log(src_base)/l

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

例如:

一个640位的数字在基数2中有640位,但在基数2中只有10位^64,所以我必须分配10个64位整数来保存结果

我目前使用的功能是:

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_基在{2,…,10+26}中,dst_基在{2^8,2^16,2^32,2^64}中

我不确定结果是否总是正确的四舍五入。Log2更容易被推理,但我读到微软Visual C++的旧版本不支持该功能。它可以像log2x=logx/log2那样被模拟,但是现在我回到了我开始的地方


GMP可能实现了一个函数来进行基转换,但我可能无法读取源代码,否则我可能会患上GPL癌症,因此我无法执行此操作。

我想速度是一个问题,或者您可以尝试基于浮点的估计,如果它太小,则可以进行调整。在这种情况下,我们可以牺牲估算速度的严密性

在下面的例子中,让dst_base为2^w,src_base为b,n_位数为n

设kb,w=max{j | b^j<2^w}。这表示b的最大幂,保证适合于w宽的二进制非负整数。由于源基和目标基的数量相对较少,这些值可以预先计算并在表中查找,但在数学上为kb,w=[w log 2/log b],其中[.]表示整数部分

对于给定的n,设m=ceil n/kb,w。那么,保存小于b^n的数字所需的dst_基位数的最大数量为:

天花板b^n-1/日志2^w≤ 天花板b^n/日志2^w ≤ 塞尔姆。日志b^kb,带日志2^w≤ m


简而言之,如果您预先计算kb,w值,您可以很快得到一个不紧的上限!n除以k,四舍五入

在这种情况下,我不确定浮点舍入,但只使用整数实现这一点相对容易,因为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的效率。 我用了无符号int而不是int。
我假设src_base是b而不是n,n是src_base中的n个数字。m=ceiln/kb,w=ceiln/w log2/logb=ceiln*logb/w log2=ceiln*logb/log2^w=ceiln_digits*logsrc_base/logdst_base,这确实是我公式的推导。我不确定这是否真的证明它是正确的四舍五入?当然,我的错误标签是正确的:我将编辑以修改。诀窍是kb,w=floor w log2/logb,而不是w*log2/logb。一方面,这意味着您可以通过采用浮点近似值并根据需要进行调整,或者通过在整数域中搜索j来精确计算kb,w,以确定2^w_uuu-b_u^j变为负值,另一方面,这意味着上面导出的m值是上界,而不是精确值。这也是一个很好的解决方案。我现在感到很难过,因为我不能同时接受两个答案。