二进制到十进制基本移位

时间:2011-01-07 16:53:42

标签: algorithm math bignum arbitrary-precision

我需要一种算法,将任意大小的无符号整数(以二进制格式存储)转换为十进制整数。即使其具有人类可读性;)
我目前使用通过十分的连续计算模数和余数的可能(或显然)有点天真的方式 不幸的是,速度有点......蹩脚。

e.g。 我计算2000 ^ 4000(使用我的bignum库)需要大约1.5秒(没有火焰请xD)。然而,包括必要的碱基转换的印刷品大约需要15分钟,这非常烦人。

我测试了bc,它在不到一秒的时间内完成了两次 它是如何做到的? (不是ffts的乘法和任何基础转换)

3 个答案:

答案 0 :(得分:2)

我目前使用可能(或显然)有点天真的方式通过十分来连续计算模数和余数。
然后你应该有O(n^2)复杂度,这应该比15分钟更好。

虽然,值得看看你是如何按10划分的。

  1. 请确保您不是通过标准的长分数长的,但更简单的分区长算法应用。
  2. 确保重复使用内存。分配10Kb块10000次肯定会妨碍您的表现。
  3. 修改
    如何在一遍中将长二进制数除以10得到结果和提醒。没有额外的记忆。
    简单的伪代码(a[0]是最高位数)

    int r = 0;
    for (int i = 0; i < n; ++i) {
        r = r * 2 + a[i];
        a[i] = r / 10;
        r = r % 10;
    }
    

    我们举个例子,编号100111011 = 315

    第0步:r = 1, a[0] = 0
    第1步:r = 2, a[1] = 0
    第2步:r = 4, a[2] = 0
    第3步:r = 9, a[3] = 0
    第4步:r = 9, a[4] = 1
    第5步:r = 9, a[5] = 1
    第6步:r = 8, a[6] = 1
    第7步:r = 7, a[7] = 1
    第8步:r = 5, a[8] = 1

    因此,提醒为5,结果为000011111 = 31

答案 1 :(得分:1)

我认为bc使用10 ^ n作为基数而不是2.所以每个内部“数字”只是n个十进制数字,至少对于十进制输入/输出,问题变得微不足道。

答案 2 :(得分:0)

无需使用取幂:

#include "stdio.h"
#include "stdlib.h"
#include "string.h"

int main(){
    char a[] = "10011";
    unsigned long int res= 0;
    int i;

    for(i = 0; i < strlen(a); i++){
        res = (res<<1) + (a[i]-'0');
    }

    printf("%d",res);
    return 0;
}

第一次更新

现在长度应该不是问题...

#include "stdio.h"
#include "stdlib.h"
#include "string.h"

char *doubles(char *);
char *sum(char *,int);

int main(){
    char a[] = "10011";
    char *res = calloc(2,sizeof(char));
    int i;

    res[0] = '0';
    for(i = 0; i < strlen(a); i++){
        res = sum(doubles(res),(a[i]-'0'));
    }

    printf("%s",res);
    return 0;
}

char *doubles(char *s){
    int i,len = strlen(s),t = 0;
    char *d;
    d = calloc(len+1,sizeof(char));
    for(i = 0; i < len; i++){
        t = ((s[len-i-1]-'0')<<1) + t;

        d[len-i] = ('0' + (t%10));
        t = t/10;
    }

    d[0] = t+'0';

    return (d[0] == '0')?d+1:d;
}

char *sum(char *s,int n){
    int i, len = strlen(s),t = n;
    char *d = calloc(len+1,sizeof(char));

    for(i = 0; i < len ; i++){
        t = (s[len-i-1]-'0') + t;
        d[len-i] = ('0' + (t%10));
        t = t/10;
    }
    d[0] = t+'0';

    return (d[0] == '0')?d+1:d;
}