7

10進数または16進数がある場合、2進数32に変更するにはどうすればよいですか?

私がこれを行おうとしている理由は、ここで他のメンバーによって提案されているようにBigIntを実装するためです。なぜBigIntを実装するためにより高いベースを使用するのですか?

2 32までは整数(基数10)と同じですか?その後はどうなりますか?

4

5 に答える 5

12

あなたは形の何かを見つけようとしています

a0 + a1 * (2^32) + a2 * (2^32)^2 + a3 * (2^32)^3 + ...

これはまさにベース232システムの定義なので、あなたの質問が意味をなさないとあなたに言ったすべての人々を無視してください!

とにかく、あなたが説明していることはベース変換として知られています。迅速な方法があり、これを解決する簡単な方法があります。簡単な方法は非常に複雑であり(この主題に特化した本の章全体があります)、ここではそれらに対処しようとはしません(特に、それらを使用しようとしたことがないため)。

簡単な方法の1つは、最初に2つの関数、乗算と加算を記数法に実装することです。(つまり、実装BigInt add(BigInt a, BigInt b)してBigInt mul(BigInt a, BigInt b))。これを解決すると、10進数を次のように表すことができます。

b0 + b1 * 10 + b2 * 10^2 + b3 * 10^3 + ...

これは次のように書くこともできます:

b0 + 10 * (b1 + 10 * (b2 + 10 * (b3 + ...

したがって、入力文字列内を左から右に移動すると、一度に1つの基数10桁をはがし、addおよびmul関数を使用して次のように累積できますBigInt

BigInt a = 0;
for each digit b {
    a = add(mul(a, 10), b);
}

免責事項:この方法は計算効率が良くありませんが、少なくとも始めることができます。

注: 2 32は16の正確な倍数であるため、ベース16からの変換ははるかに簡単です。したがって、変換は基本的にビットの連結になります。

于 2012-04-16T19:58:47.467 に答える
5

10進数について話しているとしましょう。

a[0]*10^0 + a[1]*10^1 + a[2]*10^2 + a[3]*10^3 + ... + a[N]*10^N

ここで、それぞれa[i]は0から9までの範囲の数字です。

入力値である文字列を解析して配列を見つけることができると仮定しますa[]。それができたら、 and演算子を使用してBigIntクラスを既に実装していると仮定すると、家に帰ります。クラスのインスタンスを使用して、上記の式を簡単に評価できます。+*BigInt

ホーナー法を使用すると、この式を比較的効率的に評価できます。

私はこれを頭のてっぺんから書き留めたところですが、もっと効率的なベース変換スキームがあるに違いありません。

于 2012-04-16T19:58:15.970 に答える
4

10進数または16進数がある場合、2 ^ 32を基数に変更するにはどうすればよいですか?

他のベースに変換するのと同じように。あなたは番号を書きnたい

n = a_0 + a_1 * 2^32 + a_2 * 2^64 + a_3 * 2^96 + ... + a_k * 2^(32 * k).

したがって、に分割される2 ^ 32の最大の累乗を見つけ、nその累乗の倍数をから減算し、nその差を繰り返します。

しかし、あなたは正しい質問をしたと確信していますか?

別の質問をするつもりだと思います。私はあなたが尋ねることを意味しているのではないかと思います:基数10の数を私のインスタンスに解析するにはどうすればよいBigIntegerですか?簡単だ。実装をコーディングし、実装したことを確認して+ください*。私はあなたが実際に整数を内部的に表現する方法に完全にとらわれませんが、2進数の2 ^ 32を使用したい場合は、それを実行してください。それで:

 BigInteger Parse(string s) {
      BigInteger b = new BigInteger(0);
      foreach(char c in s) { b = b * 10 + (int)c - (int)'0'; }
      return b;
 } 

これをCに変換するのはあなたに任せます。

于 2012-04-16T19:43:23.970 に答える
1

232は168であるため、ベース16は簡単です。正確な累乗ですしたがって、最下位桁から始めて、一度に8桁の16進数を読み取り、それらの桁を32ビット値に変換します。これが次の2進数の32桁です。

10進数はもっと難しいです。あなたが言うように、それが2 32未満の場合、あなたはその値を1つの底232 "桁"として取るだけです。それ以外の場合、私が考えることができる最も簡単な方法は、筆算アルゴリズムを使用して、基数10の値を232で繰り返し除算することです。各段階で、余りは次の2進数の232「桁」です。おそらく、私よりも数論を知っている人が、より良い解決策を提供できるでしょう。

于 2012-04-16T20:04:29.120 に答える
0

これは完全に合理的なことだと思います。

あなたがしているのは、32ビット整数の配列で非常に大きな数(暗号化キーのような)を表すことです。

基数16の表現は、基数2 ^ 4、または一度に一連の4ビットです。基数16の「桁」のストリームを受信して​​いる場合は、8つの「桁」を読み取るまで、配列の最初の整数の下位4ビットを入力し、次に下位の整数を入力します。次に、配列内の次の要素に移動します。

long getBase16()
{
  char cCurr;

  switch (cCurr = getchar())
  {
  case 'A':
  case 'a':
    return 10;
  case 'B':
  case 'b':
    return 11;
  ...
  default:
    return cCurr - '0';
  }
}

void read_input(long * plBuffer)
{
  long * plDst = plBuffer;
  int iPos = 32;

  *(++plDst) = 0x00;

  long lDigit;
  while (lDigit = getBase16())
  {
     if (!iPos)
     {
       *(++plDst) = 0x00;
       iPos = 32;
     }

     *plDst >> 4;
     iPos -= 4;
     *plDst |= (lDigit & 0x0F) << 28
  }
}

* plDstをiPosでシフトして終了したり、配列内の整数の数を追跡したりするなど、やるべきことがいくつかあります。

10進数から変換する作業もいくつかあります。

しかし、これはあなたが始めるのに十分です。

于 2012-04-16T20:20:02.657 に答える