6

私はこのコードを持っています

#include <iostream>

using namespace std;

int main(int argc,char **argv) {

    unsigned long long num1 = 99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999995LL;
    unsigned long long num2 = 99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999996LL;
    unsigned long long num3 = 99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999997LL;
    unsigned long long num4 = 99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999998LL;
    unsigned long long num5 = 99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999LL;

    cout << (unsigned long long)(num1 * num2 * num3 * num4 * num5) << endl;
    return 0;
}

ご覧のとおり、数字は膨大ですが、計算すると次のようになります: 18446744073709551496

コンパイル時に、次の警告が表示されます。

warning: integer constant is too large for its type|
In function `int main(int, char**)':|
warning: this decimal constant is unsigned only in ISO C90|
...
4

8 に答える 8

22

結果が long long 型よりも大きい - BigIntegerまたはgmpのような任意精度のライブラリを確認する必要があります

于 2008-10-27T18:08:00.190 に答える
7

これらの数値は、どの C++ データ型にも適合しません。それらを印刷するだけの場合は、数値を文字列に保存します。それを計算したい場合は、任意精度の数学ライブラリを見つけて使用してください。

于 2008-10-27T18:07:48.490 に答える
3

あなたは何をしようとしているのですか?2進数と10進数の基本を理解していますか?なぜ8ビットは0から255の値、12ビットは0から4095などの値しか保持しないのですか?興味のある数を保持するのに何ビットかかりますか?それ以上に、あなたはどれくらいの数を作成することに興味がありますか?そして、数字を大きくするために9を使用していますか?代わりに16進数の0xF...はどうですか?(標準の整数型の1つに含まれる)最大の符号なし数値が必要な場合は、次のようにします。

unsigned long long a、b;

a = -1; //符号付きと符号なしの混合が間違っているように見えますが、有効です。数値は、格納する前に符号なしに変換されます

b = 0; b--; //上記と同じことをします

そのレベルの精度が本当に必要ですか?乗算には、各オペランドの2倍のサイズの結果が必要になる可能性があることに気づきましたか?0xFF * 0xFF = 0xFE01、この場合、8ビット整数を使用している場合、計算を行うことができませんでした。0xFF * 0xFF * 0xFF = 0xFD02FFを掛け続けると、さらに悪化します。

何をしようとしていますか?


あなたの応答を見て:

私はこれまでオイラー番号8を見たことがありません。解決するのに数行のコードしか必要としないので、良いインタビューの質問のように聞こえます。


あなたの他の応答:

数字...

おそらく、10本の指(そしておそらく10本の足指)があるため、「ベース10」で成長します。私たちの時計はほとんどの場合基数60ですが、より混乱させるために基数10と混合されています。とにかく、基数10は、各数値プレースホルダーに対して、10の一意の数字のいずれかを持っていることを意味し、その場所で最大値に達したときに、次の場所にロールオーバーします。これはすべて小学校のものです。

000
001
002
003
...
008
009
010
011012 ..。
_

右端の数字に10個の記号(0、1、2、3、4、5、6、7、8、9)があり、最後の記号に達すると最初からやり直し、左側の数字が次のように増加する様子を確認してください。 1。この規則は、すべての基数記数法に当てはまります。

0と1の2つのシンボルしかないことを除いて、ベース2にも当てはまります。

000
001
010
011100101 ..。
_
_

8進数についても同じことが言えますが、8つの記号(0、1、2、3、4、5、6、7)

000
001
002
003
004
005
006
007
010
011
012013 ..。
_

また、16進数の16個の記号(0,1,2,3,4,5,6,7,8,9、a、b、c、d、e、f)についても同じことが言えます。

000
001
002
003
004
005
006
007
008
009
00a
00b
00c
00d 00e
00f
010
011
012
013
..
..

私は、コンピューターで他のベース(10など)よりもバイナリーを使用する理由を調べようとしていました。要するに、オンとオフ、または高と低の2つの状態を簡単に設定できます。2つの状態は、2進数の2つのシンボル1と0のようなものです。電子機器を利用可能な電圧内で2つ以上の状態に調整しようとするのは困難です。少なくとも以前は、ゼロボルト近くまたは少数のボルトより上に維持するのは困難です。比較的簡単なので、デジタル電子機器はバイナリの2つの状態を使用します。

バイナリでの人間の単純なタスクでさえ、長い時間がかかりますが、単純な2年生の数学はまだ多くの1と0です。そのため、3ビットのグループで考えることができ、0、1、2、3、4、5、6、7の数字としてよく知られている記号を使用できるため、8進数が人気になりました。しかし、2の累乗である4のグループは、人間に8進数よりもはるかに多くの精神的な計算能力を与えます。16進数は2の累乗でもある4ビットに基づいています。従来のアラビア語の基数10であるため、アルファベットの最初の6が使用されました。8進数が使用されることはめったにありません。誰かが、16進数ではなく8進数だと思っているかどうかを年齢で知ることができます。(私は16進数の世代ですが、8進数から2進数、16進数に頭を悩ませることができないため、16進数で苦労している8進数世代の人たちと協力してきました)。

コンピューターの基数10は、16進数での平均的な人間の思考のようなものです。コンピューターは基数10を実行しません(bcdを実行していた怠惰な人間の場合)。基数2を実行します。コンピューターの10進数1234は、実際には0x4D2または0b010011010010です。これは値として、1234に加えて、シンボル1、2、3、および4とは関係のないその値が必要な他の数値を追加したいとします。しかし、この回答をstackoverflowに投稿するために、数値を使用しません。 ASCIIを使用するため、asciiの1234は0x31、0x32、0x33、0x34です。これは、1000桁の数値がascii文字列として提供されていると仮定して、オイラーソリューションで知っておくことが重要です。問題は10進数の問題であり、定義上2進数ではないため、バイナリからASCIIに変換します。

さて、私が尋ねたことに戻りましょう。数値を格納するために4ビットのメモリがあるとしましょう。どのくらいの大きさの数値を格納できますか?基数10のみを考える場合、数値は9と考えるかもしれません。これは、各格納場所で最大の記号を使用することを考えるように訓練されているためです。基数10に5つの格納場所がある場合、99999が最大数です。4ビットに戻るただし、1ビットの最大の記号は1であり、1111(4つ)を取得する各保管場所にその番号を入れます。これらの4つを見るだけで、同じ数の17進数またはFの16進数の8進数と16進数のバージョンを簡単に確認できるはずです。小数を表示するには、数学、またはこの場合は暗記が必要です。その数は小数15です。したがって、使用できる最大の4ビット数は0xFまたは9ではなく15です。8ビット数はどうでしょうか。0xFFまたは255(2の8乗から1を引いたもの)。最大の16ビット数?65535など。

つまり、何ビットを使用しようとしているのかを尋ねると、これが意味します。この数値99999を見てください。ここでも基数10が最大の数値だと思いますが、コンピュータにとっては、その一部にすぎません。99999の10進数は0x1869Fであり、格納に17ビットのメモリが必要です。ストアは0x1FFFFで、これは131071で、99999より少し大きいです。したがって、コンピューターで大きな数値や数学を考えたい場合は、2進数(または16進数)を考える必要があります。

もともとあなたは掛け算をしていましたが、それはまだオイラー問題の一部ですが、私が尋ねていたのは精度とビットストレージに関連していました。ここにいくつかの基本事項があります。これについては説明しませんが、コンピューターの浮動小数点ユニットに依存している理由がわかります。

最大の4ビット数1111(2進数)を取ります。これは10進数の15です。最大の4ビット数でそれを追加すると、15 + 15 = 30=0x1Eまたは11110バイナリが得られます。したがって、2つの4ビット数を追加するには、答えを保持するために5ビットが必要です。コンピュータは、この余分なビットのために「キャリー」ビットを保持します。基本的に、コンピューターの整数の加算/減算関数を使用すると、N+1ビットを使用できます。したがって、32ビットコンピュータの場合、基本的に追加/サブ計算用に33ビットがあります。

問題は乗算と除算です。これは今日でも多くのプロセッサがサポートしていません(はい、多くのプロセッサはfpuを持たず、加算と減算のみを行い、場合によっては乗算を行いますが、除算はまれです。乗算と除算は多くの電子機器を必要とします。トレードオフは可能です。ソフトウェアで加算と減算を使用してそれらを実行します)。4ビットシステムの最悪の場合の乗算1111*1111 = 11100001 4ビット乗算の結果を格納するのに8ビットかかるので、4ビットシステムの場合、実行したい乗算のほとんどが4ビットシステムであることがすぐにわかります。 4ビットに格納できない数値になります。したがって、64ビット整数(unsigned long longは多くの場合64ビット)を取得して4倍するのを見たとき、つまり、回答を格納するには64 * 5または320ビット整数が必要であり、その回答を64の大きな結果、これはかなり頻繁に、

浮動小数点は科学的記数法にすぎませんが、2進数です。科学的記数法を使用して数値1234と5678を乗算する場合は、1.234 * 10^3に5.678*10 ^ 3を掛けると、7.007 * 10^6になります。精度を維持し、より広い範囲の数値を表すことができます。これがバイナリでどのように機能するかについては説明しません。しかし、それはあなたの元の質問には機能しません。

ああ、質問/回答で私が何をしていたかを明確にする最後のこと。2進数の負の整数。足し算と引き算と基本システムの間の関係のために、あなたはいくつかのトリックをすることができます。2進数を使用して数値7(10進数)から1を減算したいとします。減算回路のようなものはありません。代わりに負の数を加算するので、7-1の代わりに実際には7 +(-1)になり、違いが生じます。

0111 + ???? = 0110

6を取得するために7に何を追加できますか...バイナリで?

0111 + 1111 = 0110

2進数の負の数は「2の補数」と呼ばれ、簡単に言えば、答えは「1を反転して加算する」です。マイナス1を2進数でどのように表現しますか?プラス1の0001を取り、それを反転して、1を0にし、0を1にする(1の補数とも呼ばれます)1110、次に1つの1111を追加します。マイナス1は、ビット数に関係なく、コンピューターの特別な数値です。すべてのものとして表されます。したがって、誰かがこれを行うのを見ると、次のようになります。

unsigned char a;

a = -1;

コンパイラは最初にその-1を調べ、... 11111(binary)を考え、次に等号を調べ、反対側を調べます。ああ、すべて1にしたい場合は、符号付き整数と符号なし整数があることを確認します。ただし、変換はビットを移動するだけなので、上記でa=0xFFが必要であると言っています。(8ビットのunsigned charを想定)。

一部のコンパイラは、符号なし数値に負の数を格納しようとしていると文句を言う場合があります。他のコンパイラはその-1を見て、32ビットまたは最近では64ビットの符号付き整数定数と見なし、等しい値を8ビットの符号なしに評価すると、-1を符号付きに格納できないという警告が表示されます。またはタイプキャストなしのunsignedchar。しかし、これを行う場合:

a = 0; a--;

すべてのコンパイラはそれを気に入るはずです。不平を言うことはありません。コンパイル時ではなく、実行時にコンピューティングサイクルを消費するだけです。

今、どこかで友人が私にバイナリ数学を連続して行う本について教えてくれました。たとえば、数字を否定する場合、通常は1つのトリックを反転して広告しますが、鉛筆と紙を使用すると、別のトリックを教えてくれる場合があります。右から始めて、最初の1までのゼロをコピーし、その後反転するので、マイナス2

0010
1110

右から始めて0をコピーし、次に最初のビットをコピーしてから、左に進むにつれて残りのビットを反転します。

マイナス6

0110
1010

マイナス4

0100
1100

おそらく、足し算と引き算を行うためのトリックがありますが(まあ、それらは簡単です)、乗算と除算もあります。それらを連続して実行すると、同じaluを使用してバイナリで無限に長い計算を実行できます。それを行う方法を知っていれば、それをソフトウェアに実装でき、大きな定数を乗算するという元の質問(すべての精度を保持することを前提としています)は、どのコンピューターでも簡単です。

于 2008-10-28T00:58:12.780 に答える
3

コードでこれほど大きなリテラルが必要な場合は、それらを文字列リテラルとして入力し、何らかの BigInt クラスにロードする必要があります。現時点では、ソース コードでそれほど大きな整数リテラルを表現する方法はありません (ただし、C++0x ではその不足が解決されることを願っています)。

BigIntegerライブラリを使用している場合は、文字列から大きな整数を作成するstringToBigUnsigned関数を参照してください。BigIntegerUtils.hh

#include "BigUnsigned.hh"
#include "BigIntegerUtils.hh"     

 BigUnsigned  num1 = stringToBigUnsigned (
    "99999999999999999999999999999999999999999999999999999999999999999999999999999999"
    "99999999999999999999999999999999999999999999999999999999999999999999999999999999"
    "99999999999999999999999999999999999999999999999999999999999999999999999999999999"
    "99999999999999999999999999999999999999999999999999999999999999999999999999999999"
    "99999999999999999999999999999999999999999999999999999999999999999999999999999999"
    "99999999999999999999999999999999999999999999999999999999999999999999999999999999"
    "99999999999999999999999999999999999999999999999999999999999999999999999999999999"
    "99999999999999999999999999999999999999999999999999999999999999999999999999999999"
    "99999999999999999999999999999999999999999999999999999999999999999999999999999999"
    "99999999999999999999999999999999999999999999999999999999999999999999999999999999"
    "99999999999999999999999999999999999999999999999999999999999999999999999999999999"
    "99999999999999999999999999999999999999999999999999999999999999999999999999999999"
    "99999999999999999999999999999999999995"
    );
于 2008-10-27T19:22:51.147 に答える
1

得られた答え 18446744073709551496 は、999...9 が long long に割り当てられたときに切り捨てられ、さらに複数の操作がオーバーフローしたためです。その決定論的ですが、事実上、ビットのランダムなコレクションにすぎません。

于 2008-10-27T19:16:03.283 に答える
0

unsigned int はシステム ワードを表します。現在、そのワードは、システムが 32 ビットか 64 ビットかによって、2^32 -1 または 2^64 - 1 で最大になります。あなたは上限に達しています。

bignum クラスを作成するか、ネット上のクラスを使用する必要があります。

そもそも、なぜこの問題をやっているのですか?

于 2008-10-27T18:07:00.397 に答える
0

数値は範囲に収まらないため、unsigned long longGMP ライブラリを使用するか、文字列を使用して、50 のような数値の階乗を計算するために行ったように大きな数値を表すことができます。

http://codepad.org/bkWNV0JC

#include <cmath>
#include <iostream>
using namespace std;
int main()
{
  unsigned int nd, nz;   
  unsigned char *ca;   
  unsigned int j, n=50, q, temp;
  int i;
  double p;
    p = 0.0;
    for(j = 2; j <= n; j++)
    {
      p += log10((double)j);  
    }
    nd = (int)p + 1;

    ca = new unsigned char[nd+1];
    if (!ca)
    {
      cout << "Could not allocate memory!!!";
      exit(0);
    }
    for (i = 1; (unsigned)i < nd; i++)
    {
      ca[i] = 0;
    }
    ca[0] = 1;

    p = 0.0;
    for (j = 2; j <= n; j++)
    {
      p += log10((double)j);   
      nz = (int)p + 1;        
      q = 0;                  
      for (i = 0;(unsigned) i <= nz; i++)
      {
        temp = (ca[i] * j) + q;
        q = (temp / 10);
        ca[i] = (char)(temp % 10);
      }
    }

    cout << "\nThe Factorial of " << n << " is: ";
    for( i = nd - 1; i >= 0; i--)
    {
      cout << (int)ca[i];
    }
  //  delete []ca;    
  return 0;
}
于 2012-09-17T11:16:39.303 に答える