2010-05-18 32 views
11

Tôi biết cách tạo số ngẫu nhiên từ 0 đến 1 bằng phương pháp NextDouble của trình tạo số giả ngẫu nhiên.Làm thế nào để tạo ra một mật mã an toàn Double giữa 0 và 1?

var rng1 = new System.Random(); 
var random1 = rng1.NextDouble(); // generates a random double between 0 and 1.0 

Và tôi biết cách điền một mảng byte ngẫu nhiên bằng trình tạo số ngẫu nhiên bảo mật mã hóa.

Byte[] bytes = new Byte[8]; 
var rng2 = new System.Security.Cryptography.RNGCryptoServiceProvider(); 
rng2.GetBytes(bytes); // generates 8 random bytes 

Nhưng làm thế nào tôi có thể chuyển đổi sản lượng byte-mảng của RNGCryptoServiceProvider vào một số ngẫu nhiên phân bố đều giữa 0 (bao gồm) và 1 (độc quyền)?

+0

Bạn muốn phân phối gì? Đồng phục? – AakashM

+0

Có, phân bố đều. Sẽ cập nhật ngay bây giờ. – Portman

Trả lời

20

Dường như với tôi các giải pháp cho đến nay sẽ có phân phối không đồng đều do tính nghịch đảo. Đối với một phân phối thậm chí tôi nghĩ rằng bạn muốn một cái gì đó như thế này.

// Step 1: fill an array with 8 random bytes 
var rng = new RNGCryptoServiceProvider(); 
var bytes = new Byte[8]; 
rng.GetBytes(bytes); 
// Step 2: bit-shift 11 and 53 based on double's mantissa bits 
var ul = BitConverter.ToUInt64(bytes, 0)/(1 << 11); 
Double d = ul/(Double)(1UL << 53); 

Lưu ý rằng bạn không thể chỉ chia UInt64 vào UInt64.MaxValue, bởi vì một đôi không có đủ bit, và không có cách nào để có được kết quả đầu ra duy nhất cho tất cả các đầu vào của bạn. Vì vậy, bạn có thể/phải ném một số bit đi.

+0

Vâng, tôi nghĩ bạn nói đúng. –

+0

Điều này thật tuyệt vời, cảm ơn bạn. Chỉ cần thêm tham số thứ hai bắt buộc vào BitConverter.ToUInt64 và một phụ huynh bị thiếu trên dòng 2. Kiểm tra ngay bây giờ để đảm bảo nó là một phân phối tương đương với Random.NextDouble(). – Portman

+1

Chỉnh sửa số 3 hoạt động tốt: sau 1 triệu lần lặp, tối thiểu là 0,0000001, tối đa là 999999, trung bình là 5000003 sau 1 triệu lần lặp. Nếu tôi dọn sạch lịch sử chỉnh sửa thì sao? – Portman

1

Vâng, tôi sẽ không gọi một số ngẫu nhiên 64-bit "mã hóa an toàn" - bạn muốn nhiều hơn bit hơn là "mã hóa an toàn". Nhưng dù sao, bạn có thể làm một cái gì đó như thế này:

var bytes = // assume this contains 8 bytes of random numbers 

long l = BitConverter.ToInt64(bytes); 
double d = Math.Abs(1/(double)l); 
+0

Có thể muốn thêm 'Math.Abs ​​(l)' để đảm bảo kết quả là số dương. –

+0

@Paul: điểm tốt, được thêm vào. –

+4

Điều này có phân phối rất khác so với NextDouble. Nó sẽ tạo ra con số rất gần với số không gần như tất cả các thời gian. –

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