3

unsigned long long理論的には、10 進数の 19 桁の数である 2^64-1 まで格納する必要があるため、C/C++ 型と混同していますが、次のコード:

unsigned int x = 1000000u; //(One million)
unsigned long long k = (x*x);
cout << k << endl;

3567587328 が出力されますが、これは正しくありません。現在、 1,000,000^2 の結果は 1,000,000,000,000 になります。これは 10 進数 12 桁で、 even の制限をはるかに下回っていますsigned long long。これはどのように起こりますか?私が実行しているシステムと何か関係がありますか? (32 ビット Ubuntu)

64 ビット操作を実装するために 64 ビット システムが必要な場合、別の疑問が生じます。ほとんどのコンパイラは、次のように線形合同法ジェネレータを使用して乱数を生成します。

x(t) = (a*x(t-1) + c) mod m.

acは通常 32 ビットの大きな数値であり、m は です。2^32-1 そのためa*x(t-1)、モジュロ演算が実行される前に 64 ビットの数値になる可能性が高くなります。

64 ビット システムが必要な場合、gcc は 16 ~ 32 ビット マシンで 1990 年代以降、どのように乱数を生成できますか?

どうもありがとう。

4

3 に答える 3

10

確かにそうですkunsigned long long、そうでxありunsigned int、したがってそうですx*x。式は として計算され、unsigned int符号なし型の制限を超えると通常のラップアラウンドが発生します。ダメージが与えられた後、それは に変換されますunsigned long long

考えられる修正:

  • 作るx_unsigned long long
  • unsigned long long k = ((unsigned long long)x*(unsigned long long)x);
  • unsigned long long k = (1ULL*x*x);
于 2013-03-10T21:25:47.623 に答える
5

xですunsigned int-->x*xですunsigned int。乗算の結果が の最大値を超える場合unsigned int、ラップアラウンドが発生します。これらの操作の後でのみ、結果が受信変数 ( k) に代入されます。結果を次のようにしたい場合はunsigned long long、少なくとも 1 つのオペランドをこの型に昇格させる必要がありますunsigned long long k = (unsigned long long)x * x;

2 番目の質問について: コンパイラは通常、数値を生成しません。これは実行時に行われます。どこで数式を入手したのかわかりませんx(t) = (a*x(t-1) + c) mod m。これが実際に式であると仮定すると、中間結果を制限する方法があります。モジュロ演算は、結果を変更することなく、任意のオペランドまたは中間結果に適用できます。したがってx(t) = (a*x(t-1) + c) mod m = (a mod m) * (x(t-1) mod m) + c mod m

于 2013-03-10T21:39:13.913 に答える
3

右辺にunsigned intanを掛けると、結果は an になります。そのため、この値が後で に割り当てられるという事実に関係なく、乗算される 2 つの数値と同じ制限があります。unsigned intunsigned intunsigned long long

ただし、unsigned int変数をにキャストするunsigned long longと、結果は になりunsigned long long、値は のサイズに制限されませんunsigned int

unsigned long long k = (((unsigned long long)x)*((unsigned long long)x));

それはあなたが望む結果を与えるはずです。

于 2013-03-10T21:28:52.080 に答える