计算2 ^ n的高精度程序

时间:2012-11-01 02:41:24

标签: c algorithm bignum

我正在C中构建一个可以获得2幂的程序。用户输入n的值,程序将计算2^n

这是code

当我输入100

时出现问题

我得到的是什么:

1,267,650,600,228,229,400,000,000,000,000

我应该得到什么

1,267,650,600,228,229,401,496,703,205,376

它必须完全用ANSI C编码。有关如何提高精度的任何想法? N的最大值必须为256(256位,我想,这意味着最大输出应为2^256)。

我在这里缺少的是精确度,我不知道如何解决这个问题。有什么想法吗?

7 个答案:

答案 0 :(得分:4)

如果你从一开始就在10号基地工作,我认为这是最简单的。这是因为虽然二进制计算2的幂是微不足道的,但转换回基数10要困难得多。

如果您有一个基数为10的数组 1 ,您只需要实现基数10加法,并且可以乘以2(通过将数字加到自身)。在循环中执行n次,即可获得答案。

如果你想支持更高的指数,你也可以考虑通过平方来实现取幂,但这更难,因为你需要通用乘法,而不仅仅是2。

1 提示:如果以相反的顺序存储数字,会更方便。

答案 1 :(得分:2)

这是我对hammar's approach.的快速而又脏的实现,将十进制数存储为C字符串,其中数字的顺序相反。

Run the code on ideone

void doubleDecimal(char * decimal)
{
    char buffer[256] = "";
    char c;
    unsigned char d, carry = 0;
    int i = 0;

    while (c = decimal[i])
    {
        d = 2 * (c - '0') + carry;
        buffer[i] = (d % 10) + '0';
        carry = d / 10;
        i++;
    }

    if (carry > 0)
        buffer[i++] = (carry % 10) + '0';

    buffer[i] = '\0';
    strncpy(decimal, buffer, 256);
}

void reverse(char * str)
{
    int i = 0;
    int j = strlen(str) - 1;

    while (j > i)
    {
        char tmp = str[i];
        str[i] = str[j];
        str[j] = tmp;

        i++;
        j--;
    }
}

int main(void)
{
    char decimal[256] = "1";
    int i;

    for (i = 0; i < 100; i++)
        doubleDecimal(decimal);

    reverse(decimal);
    printf("%s", decimal);

    return 0;
}

输出:

1267650600228229401496703205376

答案 2 :(得分:1)

double是(可能)64位值。您不能以64位存储256位精度。你得到一个接近的数字的原因是因为浮点数以不同的精度存储 - 不是所有的序号都可以表示,但你可以代表非常大的数字。在这种情况下相当无用。 你想要的是使用任意精度库,或者,因为这可能是家庭作业,你应该自己编写。

答案 3 :(得分:1)

使用64位IEEE 754的典型double具有大约51位精度,IIRC。

最有可能支持高达256的指数超过该精度,以及long doublelong long的精度,因此您必须自己做事。

作为家庭作业,那么,

  • 将十进制数值存储在数组中+数字计数
  • 在此类数组中实现倍增+ count
  • 从1开始,双倍值适当的次数。

答案 4 :(得分:0)

您需要考虑的一些事情来解决这个问题:

  1. 您只处理整数,因此您应该使用整数 表示(你需要自己动手,因为你无法使用 长的“只有”64位长)。
  2. 你说2的权力 - 方便 - 计算机使用2的幂存储数字(你会 只需要使用移位操作和位摆弄....没有 需要乘法。)
  3. 如何将基数为2的数字转换为基数为10的数字用于显示目的(考虑除法和一次输出一个数字(想想硬件除数的作用是为了使位操作正确)。

答案 5 :(得分:0)

您不能以64位存储256位精度。要获得要关闭的数字的原因是因为浮点数以不同的精度存储。可以表示所有序列号,但您可以表示非常大的数字。在这种情况下相当无用。

答案 6 :(得分:0)

#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//constants
#define MAX_DIGITS 1000

//big integer number struct
struct bigint {
  char Digits[MAX_DIGITS];
};

//assign a value
void assign(struct bigint* Number,int Value) {
  if (Value!=1) {
    printf("Can not assign value other than 1\n");
    exit(0);
  }
  memset(Number,0,sizeof(bigint));
  Number->Digits[0] = Value;
}

//multiply the big integer number with value
void multiply(struct bigint* Number,int Value) {
  int Digit,New_Digit;
  int Carry = 0;

  for (int Index=0; Index<MAX_DIGITS; Index++) {
    Digit     = Number->Digits[Index];
    New_Digit = Digit*Value%10;
    if (New_Digit+Carry<10) {
      New_Digit = New_Digit+Carry;
      Carry     = Digit*Value/10;
    }
    else {
      New_Digit = (New_Digit+Carry)%10;
      Carry     = (Digit*Value/10)+1;
    }

    //set the new digit
    Number->Digits[Index] = New_Digit;
  }//for loop
}

//print out the value of big integer type
void print(struct bigint* Number) {
  int Index = MAX_DIGITS-1;
  while (Number->Digits[Index]==0 && Index>=0)
    Index--;

  //the big integer value is zero
  if (Index==-1) {
    printf("0");
    return;
  }

  while (Index>=0) {
    printf("%u",Number->Digits[Index]);
    Index--;
  }
}

//main programme entry point
int main(int Argc,char** Args) {
  int Power = 100;
  struct bigint Number;

  //assign the initial value
  assign(&Number,1);

  //do the multiplication
  for (int Index=0; Index<Power; Index++)
    multiply(&Number,2);

  //print result
  print(&Number);
  getch();
}

//END-OF-FILE