2009-07-31 38 views
7

Tôi muốn có một số ngẫu nhiên như thế này: (trong C#)đặc biệt ngẫu nhiên số

Random r = new Random(); 
r.next (0,10) 

NHƯNG điều quan trọng là các số ngẫu nhiên được hơn gần 8, (hoặc nó được thường lớn), Ý tôi là nếu chúng tôi sử dụng cho:

for (int i =0; i<...;i++) 
{ 
    write: r.next (0,10) 
} 

kết quả là như thế này;

8 7 6 9 1 0 5 3 2 
2 3 8 9 7 7 6 2 3 
8 8 9 7 2 8 2 8 4 
3 
+5

Vì vậy, bạn đang yêu cầu cho số ngẫu nhiên mà, err, không phải là ngẫu nhiên? – blowdart

+12

Không, anh ta không, anh ta chỉ muốn một bản phân phối khác (giống Gauss hơn 8, không phân bố đều trên tất cả các số) – schnaader

+1

Tôi muốn tạo các số ngẫu nhiên có trọng số. –

Trả lời

2

Bạn cần một chức năng phân phối mà phải mất một số giữa 0 và 1 và chuyển nó đến một số trong phạm vi mà bạn muốn, với một trọng lượng cao hơn trên một số cụ thể. Bạn có thể tạo ra một hàm như vậy với các hàm lượng giác (sin, cos, ...), mũ, hoặc có thể là đa thức.

UPDATE: Có một cái nhìn tại this page để biết thêm thông tin về phân bố xác suất

+1

WTF là một đa thức? Methinks bạn đã đi cho nút "Đăng câu trả lời của bạn" quá nhanh – paxdiablo

+3

đa thức là hàm đại số được viết theo dạng: f (x) = an * x^n + (an-1) * x^(x-1) + ... a2 * x^2 + a1 * x + a0; –

+0

Không, đó sẽ là một * đa thức *. Tôi thấy không ai ở đây đánh giá cao (của tôi-lạ, theo cô ấy phải được tuân theo) hài hước. Tôi nghĩ tôi sẽ đi ngủ. – paxdiablo

29

Bạn cần cân nhắc kết quả của mình. Bạn có thể làm điều đó với một cái gì đó như thế này:

private int[] _distribution = new int[] { 0, 1, 2, 3, 4, 5, 6, 6, 7, 7, 8, 8, 8, 9, 9 }; 
Random _r = new Random(); 

public int GetWeightedRandom() 
{ 
    return _distribution[_r.Next(0, _distribution.Length)]; 
} 

Nếu tôi biết phạm vi của tôi là nhỏ và nhất quán, tôi sẽ sử dụng bảng - nó tầm thường để biến nó thành lớp riêng.

Để hoàn thành, tôi cũng sẽ thêm lớp này vào. Lớp này mượn từ xử lý hình ảnh và sử dụng chức năng sửa gamma: giá trị từ 0 đến 1 được tăng lên gamma, trả về giá trị từ 0 đến 1 nhưng phân phối nhiều hơn đến mức thấp nếu gamma < 1.0 và nhiều hơn nữa đến mức cao nếu gamma> 1.0.

public class GammaRandom { 
    double _gamma; 
    Random _r; 

    public GammaRandom(double gamma) { 
     if (gamma <= 0) throw new ArgumentOutOfRangeException("gamma"); 
     _gamma = gamma; 
     _r = new Random(); 
    } 
    public int Next(int low, int high) { 
     if (high <= low) throw new ArgumentOutOfRangeException("high"); 
     double rand = _r.NextDouble(); 
     rand = math.Pow(rand, _gamma); 
     return (int)((high - low) * rand) + low; 
    } 
} 

(từ bình luận, chuyển r ra khỏi GetWeightedRandom(). Ngoài ra bổ sung phạm vi kiểm tra để Tiếp())

OK, chúng ta hãy thực sự đi đến thị trấn ở đây. Tôi đang channeling John skeet cho điều này - nó là một lớp trừu tượng với một thuộc tính template trả về một hàm biến đổi ánh xạ phạm vi [0..1) đến [0..1) và chia tỷ lệ ngẫu nhiên cho phạm vi đó. Tôi cũng reimplemented gamma về nó và thực hiện tội lỗi và cos là tốt.

public abstract class DelegatedRandom 
{ 
    private Random _r = new Random(); 
    public int Next(int low, int high) 
    { 
     if (high >= low) 
      throw new ArgumentOutOfRangeException("high"); 
     double rand = _r.NextDouble(); 
     rand = Transform(rand); 
     if (rand >= 1.0 || rand < 0) throw new Exception("internal error - expected transform to be between 0 and 1"); 
     return (int)((high - low) * rand) + low; 
    } 
    protected abstract Func<double, double> Transform { get; } 
} 

public class SinRandom : DelegatedRandom 
{ 
    private static double pihalf = Math.PI/2; 
    protected override Func<double, double> Transform 
    { 
     get { return r => Math.Sin(r * pihalf); } 
    } 
} 
public class CosRandom : DelegatedRandom 
{ 
    private static double pihalf = Math.PI/2; 
    protected override Func<double, double> Transform 
    { 
     get { return r => Math.Cos(r * pihalf); } 
    } 
} 
public class GammaRandom : DelegatedRandom 
{ 
    private double _gamma; 
    public GammaRandom(double gamma) 
    { 
     if (gamma <= 0) throw new ArgumentOutOfRangeException("gamma"); 
     _gamma = gamma; 
    } 
    protected override Func<double, double> Transform 
    { 
     get { return r => Math.Pow(r, _gamma); } 
    } 
} 
+0

Ah, bạn đánh tôi với câu trả lời này. +1. –

+3

Điều này là tốt cho các con số tương đối nhỏ, nhưng nếu bạn muốn phân phối tập trung vào 1000000, bạn cần một mảng thực sự lớn ... Tôi nghĩ sẽ tốt hơn nếu sử dụng một hàm phân phối. –

+0

8 là một ví dụ, trên thực tế chúng tôi có: int sâu thay vì 10, và không có gì thay vì 8 (có nghĩa là gần 8 hoặc 7 hoặc 9) –

0

Dường như với tôi như bạn muốn số ngẫu nhiên của bạn được cân nhắc theo hướng cao cấp - đây có phải là đánh giá hợp lý không?

Something như this có thể giúp bạn (đó là Java, nhưng các nguyên tắc áp dụng)

+0

Không, không công bằng, nhưng điều quan trọng là vậy. –

2

Thay vì sử dụng các biến mảng, bạn cũng có thể có một cái nhìn tại SO answer này trong đó có một liên kết đến Math.NET Iridium mà thực hiện phát ngẫu nhiên không đồng nhất .

Ưu điểm của biến thể mảng là bạn có được một cách tiếp cận năng động hơn mà không phải viết lại mảng đó mọi lúc. Bạn cũng có thể làm một số điều mà thực tế là không thể với biến thể mảng (số ngẫu nhiên không đồng đều lớn).

1

Với một số loại trọng số bổ sung có thể thực hiện được. Phụ thuộc vào cách bạn chỉ định "gần tám". Một cách rất đơn giản để thực hiện điều này là:

for (int i =0; i<...;i++) 
{ 
    n = r.next (0,100); 
    write: (n*n)/1000 
} 

Bình phương sẽ cân các con số về phía cuối thấp, tức làtrong trường hợp này, 33% thời gian bạn sẽ nhận được một số 0, trong khi bạn sẽ nhận được số tiền 9 chỉ khoảng 5% thời gian.

Phương pháp này tất nhiên sẽ được điều chỉnh để phù hợp với trường hợp cụ thể.

1

Không chính xác những gì bạn đang tìm kiếm nhưng một cách rất đơn giản để ước tính phân phối số bình thường là bằng cách thêm nhiều thế hệ lại với nhau.

Một ví dụ điển hình về kỹ thuật này là trong trò chơi Dungeons và Dragons, nơi một nhân vật có thể được xác định bằng cách lăn ba con xúc xắc sáu mặt và thêm kết quả. Điều này cho một phạm vi từ 3 đến 18 với số lượng khoảng 10 khả năng nhiều nhất. Các biến thể bao gồm:

  • Lăn 4 con xúc xắc và loại bỏ mức thấp nhất. Điều này nghiêng phân phối theo hướng số cao hơn.
  • Lấy trung bình điểm số thay vì thêm chúng. Điều này làm cho phạm vi đầu ra dễ hiểu hơn.

Ngoài ra, this là khá chặt chẽ ...