将无限长基数2 ^ 32数转换为可打印基数10的算法

时间:2009-11-27 15:51:28

标签: c decimal largenumber

我将无限精确整数表示为无符号整数数组,以便在GPU上进行处理。出于调试目的,我想打印其中一个数字的基数10表示,但我很难绕过它。这就是我想做的事情:

//the number 4*(2^32)^2+5*(2^32)^1+6*(2^32)^0
unsigned int aNumber[3] = {4,5,6};
char base10TextRepresentation[50];
convertBase2To32ToBase10Text(aNumber,base10TextRepresentation);

有关如何解决此问题的任何建议吗?

编辑:感谢drhirsch

,这是一个完整的实现
#include <string.h>
#include <stdio.h>
#include <stdint.h>

#define SIZE 4

uint32_t divideBy10(uint32_t * number) {
  uint32_t r = 0;
  uint32_t d;
  for (int i=0; i<SIZE; ++i) {
    d = (number[i] + r*0x100000000) / 10;
    r = (number[i] + r*0x100000000) % 10;
    number[i] = d;
  }
  return r;
}

int zero(uint32_t* number) {
  for (int i=0; i<SIZE; ++i) {
    if (number[i] != 0) {
      return 0;
    }
  }
  return 1;
}

void swap(char *a, char *b) {
  char tmp = *a;
  *a = *b;
  *b = tmp;
}

void reverse(char *str) {
  int x = strlen(str);
  for (int y = 0; y < x/2; y++) {
    swap(&str[y],&str[x-y-1]);
  }
}

void convertTo10Text(uint32_t* number, char* buf) {
  int n = 0;
  do {
    int digit = divideBy10(number);
    buf[n++] = digit + '0';
  } while(!zero(number));
  buf[n] = '\0';
  reverse(buf);
}

int main(int argc, char** argv) {
  uint32_t aNumber[SIZE] = {0,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF};
  uint32_t bNumber[4] = {1,0,0,0};

  char base10TextRepresentation[50];

  convertTo10Text(aNumber, base10TextRepresentation);
  printf("%s\n",base10TextRepresentation);
  convertTo10Text(bNumber, base10TextRepresentation);
  printf("%s\n",base10TextRepresentation);
}

4 个答案:

答案 0 :(得分:4)

如果您可以访问64位算术,则更容易。我会按照以下方式做点什么:

int32_t divideBy10(int32_t* number) {
    uint32_t r = 0;
    uint32_t d;
    for (int i=0; i<SIZE; ++i) {
        d = (number[i] + r*0x100000000) / 10;
        r = (number[i] + r*0x100000000) % 10;
        number[i] = d;
        number[i] = r;
}

void convertTo10Text(int32_t* number, char* buf) {
    do {
        digit = divideBy10(number);
        *buf++ = digit + '0';
    } while (!isEqual(number, zero));
    reverse(buf);
}

isEqual()和reverse()将被实现。 divideBy10除以10并返回余数。

答案 1 :(得分:4)

基本上,您需要使用数字生成进行经典十进制打印,方法是将数字除以十(在基数2 ^ 32中),并将余数用作数字。您可能没有划分(任何事情,更不用说)10例程,这可能是您问题的主要来源。

如果您使用的是C或C ++,则可以从GNU Bignum package获得完整的无限精度算术包。大多数其他广泛使用的语言都有类似的软件包。

当然,如果你有太多的空闲时间,你可以自己实施多精度划分。你已经从Knuth那里借用了术语;他还在Seminumerical Algorithms中提供多精度算法。

答案 2 :(得分:3)

如果是.NET,请查看this implementation of a BigInteger class

答案 3 :(得分:0)

使用长双打怎么样?然后你在尾数中得到80位,但我猜想使用浮点数时精度会丢失。