2011-02-09 50 views
8

Tôi quan tâm đến C++, mặc dù tôi nghi ngờ rằng chỉ cần nhập định nghĩa chuẩn C. Tôi tin rằng câu trả lời là không cho những gì tiêu chuẩn nói, nhưng tôi quan tâm nhất đến câu trả lời trong thực tế.Giá trị của RAND_MAX luôn luôn (2^n) -1?

Nếu RAND_MAX luôn là (2^n) -1, đơn giản hóa việc xử lý sự cố đã bật mã di chuyển gần đây từ MinGW GCC sang Linux GCC. RAND_MAX có vẻ lớn hơn (tôi không kiểm tra, nhưng có thể bằng INT_MAX hoặc bất kỳ biểu tượng nào), vì vậy một số mã RAND_MAX-không-lớn-đủ-để-làm-xung-quanh cũ đã bị phản tác dụng. Bây giờ tôi cần phải quyết định tổng thể tôi cần thư viện này như thế nào, xem xét tính không phù hợp của việc viết mã đối phó chính xác với khả năng tràn mà không đưa ra các giả định về ví dụ. chiều rộng của một int.

Dù sao, có bất kỳ trình biên dịch C++ được sử dụng rộng rãi hợp lý nào sử dụng thứ gì khác hơn (2^n) -1 cho RAND_MAX không?

Ngoài ra, tôi có đúng không ((RAND_MAX | (RAND_MAX >> 1)) == RAND_MAX) luôn luôn và chỉ đúng nếu RAND_MAX bằng ((2^n) -1) đối với một số nguyên không dấu n. Tôi tin rằng RAND_MAX về mặt kỹ thuật là một int, nhưng nó không có ý nghĩa để có một giá trị âm hoặc phân số, vì vậy tôi nghĩ rằng tôi có thể giảm giá một cách an toàn. Bit-fiddling thường không làm phiền tôi, nhưng tôi cứ nghĩ biểu hiện có vẻ sai, và tôi không thể hiểu tại sao.

Cuối cùng, mặc dù tôi sẽ không hạnh phúc cho đến khi tôi có giải pháp làm việc của riêng mình, những gì nên Tôi đang sử dụng số ngẫu nhiên thay vì tự viết? Tôi cần số ngẫu nhiên trong phạm vi 0 < = tham số x < và tôi đặc biệt muốn xác suất bằng nhau cho tất cả các số. Ví dụ, tham gia (rand()% upperbound) cho một thiên vị đối với các giá trị nhỏ hơn, đặc biệt khi upperbound là lớn - tôi muốn tránh điều đó.

Có điều Boost hoặc C++ 0x cho điều đó không?

EDIT

Tiếp theo một cái gì đó trong "liên quan" chút ở mặt bên của trang hiển thị có thực sự là một cách để có được số ngẫu nhiên với cho giới hạn thấp hơn và cao hơn trong tăng.

Trả lời

3

Tôi không biết những gì đảm bảo trên RAND_MAX là, nhưng bạn nên tránh nó nếu có thể vì số lượng triển khai bị hỏng xung quanh và bởi vì nó bắt đầu đi xe đạp khá nhanh chóng trong các ứng dụng ngày nay. Việc phân phối đồng đều được mô tả here.

Thay vào đó, tôi khuyên bạn nên sử dụng Boost.Random. Máy phát điện Mersenne twister thể hiện sự cân bằng tốt giữa tốc độ, mức sử dụng bộ nhớ và chất lượng.

+0

Tôi đã có một thực hiện twister Mersenne - không có lý do chính đáng, chỉ cần nó được đề cập trong một cuốn sách. Một phiên bản thư viện tốt sẽ thực tế hơn, tất nhiên. Cảm ơn vì những lời khuyên. – Steve314

+1

Tôi muốn chuyển sang Tăng tốc nếu tôi là bạn; nó phân tách rõ ràng PRNG khỏi các phân bố xác suất và bao gồm một lớp 'random_device' cho việc gieo giống thích hợp (http://www.boost.org/doc/libs/release/doc/html/boost/random_device.html). –

+0

Được chấp nhận khoảng 80% vì những quan niệm sai lầm về liên kết rand - điểm Boost là thực tế hơn, nhưng liên kết đó rất thú vị. – Steve314

5
  • Tôi không biết bất kỳ triển khai nào mà RAND_MAX không nhỏ hơn một sức mạnh của hai, nhưng điều đó không được bắt buộc theo tiêu chuẩn;

  • ((RAND_MAX | (RAND_MAX >> 1)) == RAND_MAX) thực sự là một cách để kiểm tra xem RAND_MAX có nhỏ hơn sức mạnh của hai hay không.

  • Tôi đang sử dụng

    int alea(int n){ 
        assert (0 < n && n <= RAND_MAX); 
        int partSize = 
        n == RAND_MAX ? 1 : 1 + (RAND_MAX-n)/(n+1); 
        int maxUsefull = partSize * n + (partSize-1); 
        int draw; 
        do { 
        draw = rand(); 
        } while (draw > maxUsefull); 
        return draw/partSize; 
    } 
    

để làm như phân bố đều như số ngẫu nhiên có thể từ rand().

+0

Tôi có thể ' t khá sử dụng chức năng đó, bởi vì RAND_MAX là vấn đề quá nhỏ vẫn còn tồn tại trên Windows. Điều đó nói rằng, tôi chỉ có thể biên dịch có điều kiện để lựa chọn giữa điều đó và phiên bản sử dụng-hai-randoms-to-make-one (mã hiện tại không kết hợp với một cái gì đó rất giống với mã của bạn). Đó là những gì tôi đã làm để đóng các lỗi cho thời điểm này anyway - nó chỉ có vẻ như gian lận là tất cả. – Steve314

4

Để triển khai rand sử dụng (biến thể của a) Máy phát điện tuyến tính tuyến tính (phần lớn), thì RAND_MAX sẽ là số nguyên tố, không nhất thiết là dạng 2^n - 1 ("Mersenne prime") .

Ngoài ra, 2^31-1 là số nguyên tố, nhưng nếu n không phải là số nguyên tố, 2^n - 1 không phải là số nguyên tố.

(Trên thực tế, nếu n = ab, sau đó 2^n - 1 = (2^a - 1) (1 + 2^b + 2^(2b) + ...))

Khoảng 2^64, Mersenne nguyên tố duy nhất là 2^61 - 1.

Và bạn thực sự nên tránh các máy tạo đồng tuyến tuyến tính nếu bạn có bất kỳ yêu cầu nghiêm trọng nào về tạo số ngẫu nhiên. Trên thực tế, tôi muốn nói rằng ngoại trừ một trò chơi Tetris, bạn nên tránh rand() từ thư viện C.

+1

Thú vị. OTOH - "tetris" không thực sự xa so với nhãn hiệu - và đối với rất nhiều người, không chỉ cho tôi.Số lượng người phát triển thư viện mã hóa bảo mật quan trọng hoặc các ứng dụng khác mà bạn thực sự quan tâm đến cách trình tạo ngẫu nhiên thực sự, có lẽ là khá nhỏ so với ví dụ: số lượng người muốn bổ sung các bài kiểm tra hồi quy của họ với một số bài kiểm tra dựa trên dữ liệu thử nghiệm ngẫu nhiên hoặc số người viết các trò chơi đơn giản. – Steve314

+0

@ Steve314: Tuyến tính cong. máy phát điện có sai sót nghiêm trọng khiến chúng không thể ngay cả đối với các ứng dụng toán học đơn giản nhất. Xem ví dụ. http://www.javamex.com/tutorials/random_numbers/lcg_planes.shtml để xem ý tôi là gì. –

+0

các từ khóa là "ứng dụng toán học" và tôi có thể chấp nhận rằng ngay cả đối với một số ứng dụng rất đơn giản, bạn có thể cần một trình tạo mạnh hơn. Tôi sẽ thêm "mô phỏng kỹ thuật", cũng có thể xuất hiện trong "các ứng dụng khác của tôi nơi bạn thực sự quan tâm". Nhưng nghiêm túc - đối với nhiều lập trình viên, những con số ngẫu nhiên là thứ chúng ta hiếm khi cần, và khi chúng ta làm 'rand' gần như luôn đủ tốt. Đôi khi, ngay cả "thêm một số cuối cùng" là đủ để tạo ra một số dữ liệu tùy ý, tiết kiệm phức tạp nhỏ của seeding và tìm kiếm các tiêu đề bên phải để bao gồm. – Steve314

1

Trong GCC (4.6) RAND_MAX = 0x7FFFFFFF (31bit) Trong MS Visual Studio (2012) RAND_MAX = 0x7FFF (15bit)

1

Trong Embacadero C++ Builder, có hai biến định nghĩa trong stdlib.h:

/* Maximum value returned by "rand" function*/ 
#define RAND_MAX 0x7FFFU 

/* Maximum value returned by "_lrand" function (also used by random() macro)*/ 
#define LRAND_MAX 0x7FFFFFFFU 
1

trong tập tin tiêu đề chuẩn GNU, stdlib.h, có một định nghĩa về RAND_MAX mà nên là định nghĩa duy nhất trong hệ thống của bạn:

#define RAND_MAX 2147483647 

giá trị 2147 483647 = 0x7fffffff là số nguyên 32 bit không dấu lớn nhất.

Hàm rand, được xác định trong stdlib.h, đáng tin cậy trong môi trường GNU chuẩn với một cảnh báo: môi trường đa luồng (pthread) sẽ cần mã pthread để đồng bộ hóa để bảo vệ rand(), srand(), và rand_r() gọi vì chúng không reentrant. Xem man page for srand để được giải thích.

RAND_MAX không được xác định ở bất kỳ nơi nào khác trong hệ thống của bạn. Nếu bạn nhìn thấy một giá trị khác nhau cho RAND_MAX hoặc nhìn thấy một định nghĩa của RAND_MAX ở đâu đó ngoài stdlib.h, thì đây phải là một môi trường không chuẩn, không di động. Windows nổi tiếng vì việc tiêu chuẩn hóa và tính di động khó khăn (ví dụ: việc triển khai ổ cắm và API).

+1

Đây không chính xác "giá trị 2147483647 = 0x7fffffff là số nguyên 32 bit không dấu lớn nhất". Giá trị 4294967295 = 0xffffffff là số nguyên 32 bit không dấu lớn nhất. Có lẽ bạn có nghĩa là "... số nguyên lớn nhất _signed_ 32 bit". – chux

Các vấn đề liên quan