5

の累乗を得ることができるCでプログラムを構築してい2ます。ユーザーが の値を入力するnと、プログラムは を計算し2^nます。

コードは次のとおりです。

問題は入力時に発生します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)。

ここに欠けているのは精度であり、それを修正する方法がわかりません。何か案は?

4

7 に答える 7

4

最初から 10 進法で作業するのが最も簡単だと思います。これは、バイナリで 2 の累乗を計算するのは簡単ですが、基数 10 に戻すのは非常に難しいためです。

基数 10 の数字1の配列がある場合、キャリーを使用して基数 10 の加算を実装するだけで、2 を掛けることができます (数値をそれ自体に加算することによって)。そのn回数をループで実行すると、答えが得られます。

より高い指数をサポートしたい場合は、2 乗によるべき乗の実装を検討することもできますが、そのためには 2 だけでなく、一般的な乗算が必要になるため、それは困難です。

1ヒント: 数字を逆順に格納すると便利です。

于 2012-11-01T03:13:00.360 に答える
2

これは、ハンマーのアプローチの私の迅速で汚い実装です。10 進数を C 文字列として格納し、数字を逆順にします。

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
于 2012-11-01T03:42:34.063 に答える
1

double は (おそらく) 64 ビット値です。256 ビットの精度を 64 ビットに格納することはできません。近い数値を取得している理由は、浮動小数点数がさまざまな精度で格納されているためです。すべての連続した数値を表すことができるわけではありませんが、非常に大きな数値を表すことができます。この場合はかなり役に立ちません。必要なのは、任意精度のライブラリを使用するか、これはおそらく宿題なので、独自に作成することです。

于 2012-11-01T02:49:49.540 に答える
1

double64 ビットの IEEE 754 を使用する一般的なは、約 51 ビットの精度、IIRC を持っています。

おそらく、256 までの指数をサポートするポイントは、その精度を超えることであり、また along doubleまたはの精度も超えるlong longため、自分で処理を行う必要があります。

それでは、宿題の練習として、

  • 10 進数値を配列 + 桁数に格納します
  • そのような配列の値の 2 倍 + カウントを実装します。
  • 1 から始めて、値を適切な回数倍増します。
于 2012-11-01T03:11:14.923 に答える
0

256 ビットの精度を 64 ビットに格納することはできません。数値を閉じる理由は、浮動小数点数がさまざまな精度で格納されているためです。すべての連番を表すことができますが、非常に大きな数を表すことができます。この場合はかなり役に立ちません。

于 2012-11-01T03:06:58.173 に答える
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
于 2012-11-01T03:38:25.233 に答える
0

これを解決するために考えたいことがいくつかあります。

  1. 整数のみを扱っているので、整数表現を使用する必要があります (64 ビット長のみの long long を使用できないため、独自のものをロールする必要があります)。
  2. あなたが言う 2 のべき乗 - なんと便利なことでしょう - コンピューターは 2 のべき乗を使用して数値を格納します (シフト操作とビット操作のみを使用する必要があります .... 乗算は必要ありません)。
  3. 表示目的で基数 2 の数値を基数 10 の数値に変換するにはどうすればよいでしょうか (除算と一度に 1 つの数値を出力することを考えてください (ビット操作を正しく行うためにハードウェア除数が何をするかを考えてください))。
于 2012-11-01T03:02:34.280 に答える