2013-03-10 27 views
2

我與C/C++ unsigned long long類型混淆,因爲理論上它應該存儲多達19個十進制數字的2^64-1,但以下代碼:unsigned long long將不會存儲大數字

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 - 十進制數字12的數字,低於極限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自20世紀90年代以來如何在16-32位機器上生成隨機數?

非常感謝。

+1

將x改爲long long,它會起作用。 – 2013-03-10 21:30:10

回答

4

xunsigned intx*x也是unsigned int。如果乘法結果超過最大值unsigned int,則會發生環繞。 只有在這些操作後,結果才被分配到接收變量(k)。如果您希望結果爲unsigned long long,則需要將至少一個操作數提升爲此類型,例如:unsigned long long k = (unsigned long long)x * x;

關於第二個問題:編譯器通常不會生成數字,這是在運行時完成的。我不確定你在哪裏得到公式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

+0

你的答案是太棒了。 順便說一句這個公式被用在許多具有不同參數的編譯器中,如下所述:http://en.wikipedia.org/wiki/Linear_congruential_generator。 非常感謝。 – 2013-03-11 02:28:06

10

當然kunsigned long long,但是xunsigned int,因此也是x*x。您的表達式計算爲unsigned int,當遇到無符號類型的限制時,會導致通常的迴繞。損壞完成後,它將轉換爲unsigned long long

可能的修正:

  • 使xunsigned long long
  • unsigned long long k = ((unsigned long long)x*(unsigned long long)x);
  • unsigned long long k = (1ULL*x*x);
+0

非常感謝你,我從來沒有被教導過,在分配給其他變量之前,'int * int'的結果將被包裹在'int'中。 – 2013-03-11 02:23:29

3

當你乘的unsigned int通過右側的unsigned int,結果是一個unsigned int。因此,它與兩個數字相乘時具有相同的限制,而不管該值隨後分配給unsigned long long

但是,如果您將unsigned int變量投射到unsigned long long,結果將爲unsigned long long,並且該值不會被限制爲unsigned int的大小。

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

這應該給你想要的結果。

+0

很好的答案,謝謝。 – 2013-03-11 02:23:50

相關問題