1

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

例如,我计算 2000^4000(使用我的 bignum 库)大约需要 1.5 秒(请不要燃烧 xD)。然而,包括必要的基本转换在内的打印需要大约 15 分钟,这很烦人。

我已经测试了 bc ,它在不到一秒的时间内完成了这两项工作。
它是如何做到的?(不是带有 ffts 的乘法东西,以及任何只有基本转换的东西)

4

3 回答 3

2

我目前使用可能(或显然)有点幼稚的方法,通过除以十来连续计算模数和余数。
然后你应该有O(n^2)复杂性,它应该比 15 分钟好得多。

虽然,值得看看你是如何精确地除以10.

  1. 确保您应用的不是long by long 的通用除法,而是更简单的long 数除法算法。
  2. 确保重用内存。分配 10Kb 块 10000 次肯定会妨碍您的性能。

编辑
如何一次将长二进制数除以 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

于 2011-01-07T17:48:18.053 回答
1

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

于 2011-01-07T18:28:27.093 回答
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;
}
于 2011-01-07T17:35:44.320 回答