2011-10-27 9 views
19

Bu kodun neden C++ 11'deki yeni <random> üstbilgisini kullanma girişiminin doğru olduğunu anlamakta zorlanıyorum [0, 2**62 - 1]'da rastgele sayılar oluşturuyor ancak [0, 2**63 - 1] veya [0, 2**64 - 1].Neden uniform_int_distribution <uintmax_t> 62 bit numaralar için çalışıyor, ancak 63 veya 64 bit olanlar için değil?

#include <iostream> 
#include <stdint.h> 
#include <random> 
#include <functional> 
#include <ctime> 

static std::mt19937 engine; // Mersenne twister MT19937 

void print_n_random_bits (unsigned int n); 

int main (void) { 
    engine.seed(time(0)); 
    print_n_random_bits(64); 
    print_n_random_bits(63); 
    print_n_random_bits(62); 
    return 0; 
} 

void print_n_random_bits (unsigned int n) 
{ 
    uintmax_t max; 

    if (n == 8 * sizeof(uintmax_t)) { 
    max = 0; 
    } else { 
    max = 1; 
    max <<= n; 
    } 
    --max; 

    std::uniform_int_distribution<uintmax_t> distribution(0, max); 

    std::cout << n << " bits, max: " << max << std::endl; 
    std::cout << distribution(engine) << std::endl; 
} 

Şimdi, biraz daha kazma doğru davranışa sahip olan std::mt19937_64 ortaya çıkarır, ancak 62 bitlik sayı için çalışan bir şey 64 bit biri için çalışmıyor neden kimse bana açıklayabilir misin?

Edit: Üzgünüz, sorunu bile belirtmedim.

% ./rand      
64 bits, max: 18446744073709551615 
1803260654 
63 bits, max: 9223372036854775807 
3178301365 
62 bits, max: 4611686018427387903 
2943926730538475327 

% ./rand         
64 bits, max: 18446744073709551615 
1525658116 
63 bits, max: 9223372036854775807 
2093351390 
62 bits, max: 4611686018427387903 
1513326512211312260 

% ./rand              
64 bits, max: 18446744073709551615 
884934896 
63 bits, max: 9223372036854775807 
683284805 
62 bits, max: 4611686018427387903 
2333288494897435595  

Düzenleme 2: sorun 63 ve 64 bit maksimum değerleri için çıkış aralığına [0, 2**32 - 1] bir sayı, örneğin sürekli olmasıdır Ben clang++ (Apple clang version 2.1 (tags/Apple/clang-163.7.1)) ve "libc'yi kullanıyorum ++ ". Sürümüm c++0x desteğim olmadığı için GCC ile kolayca test edemiyorum.

+0

Tam olarak ne yapmak beklenmiyor? Yani, beklentilerinizden farklılık gösteren sonuçlarla size tam olarak ne denli sunuluyor? – andand

+0

Ayrıca, hangi standart kütüphane uygulamasını kullanıyorsunuz? – Fanael

+4

Belki de sadece kötü şansı düşünün :) – Dani

cevap

23

libC++ 'da bir hata buldunuz. Teşekkürler!!! . Bu düzeltme ++ ikili libc'nin dylib recompile gerektirmez

Index: include/algorithm 
=================================================================== 
--- include/algorithm (revision 143102) 
+++ include/algorithm (working copy) 
@@ -2548,7 +2548,7 @@ 
     { 
      __u = __e_() - _Engine::min(); 
     } while (__u >= __y0_); 
-  if (__w0_ < _EDt) 
+  if (__w0_ < _WDt) 
      _S <<= __w0_; 
     else 
      _S = 0; 
@@ -2561,7 +2561,7 @@ 
     { 
      __u = __e_() - _Engine::min(); 
     } while (__u >= __y1_); 
-  if (__w0_ < _EDt - 1) 
+  if (__w0_ < _WDt - 1) 
      _S <<= __w0_ + 1; 
     else 
      _S = 0; 

:

Ben ipucu-of-the gövdesine revizyon 143.104 aşağıdaki düzeltmeyi işledim.

+0

Vay, hızlı iş! Sağol Howard. – Nick

+0

LibC++'da kullanılan algoritmanın bu konuda okuyabileceği bilinen bir adı var mı? –

+2

Bilmiyorum. Algoritma, bağımsız_bits_engine için standart özelliklerde belirtilmiştir. –

0

std::mt19937, 32 bit sürüm olduğundan, büyük olasılıkla, bitin ne zaman üretileceği ve bir sonraki sayı üretilirken "çalışma alanında" önemli olmadığı varsayımları yapmaktır. Bu, son iki biti içerebilecek sayıları üretirken taşma ile sonuçlanır. Gerçek dağıtımın, 32 bit motorda 2**32 - 1'dan daha yüksek maksimum sayılarla gerçekten tekdüze olmadığını fark ettim.

+0

Bundan emin değilsiniz. Kısa araştırmalar, dağılımın 1.000.000 üretilmiş tamsayıya dayanarak, en fazla 2 ** 62 - 1 uniform olan tekdüze ya da enine yakın olduğunu göstermektedir. – Nick

+1

"mt19937" 32 bit sayıları döndürse bile, "uniform_int_distribution" 62/63/64-bit sayılarını oluşturmak için birden çok kez çağırmamalıdır? – interjay