Cách nhanh nhất để tạo boolean ngẫu nhiên


87

Vì vậy, có một số cách để tạo bool ngẫu nhiên trong C #:

  • Sử dụng Random.Next (): rand.Next(2) == 0
  • Sử dụng Random.NextDouble (): rand.NextDouble() > 0.5

Có gì khác sao? Nếu vậy, cái nào thực sự có hiệu suất tốt hơn? Hay là có một cách khác mà tôi không thấy, cách đó thậm chí có thể nhanh hơn?



7
Đây có thực sự là điểm nghẽn?
Brian Rasmussen

2
Nếu không thực sự chạy nó (bởi vì bất kỳ phương thức nào cũng sẽ nhanh chóng mặt), suy đoán của tôi sẽ là sử dụng NextBytesđể điền trước một mảng byte, sử dụng BitArrayđể biến nó thành một tập hợp các boolean và truy xuất các boolean đó từ một Queuecho đến khi nó được làm trống, sau đó lặp lại quá trình. Với phương pháp này, bạn chỉ sử dụng bộ ngẫu nhiên một lần, vì vậy mọi chi phí mà nó tạo ra chỉ xảy ra khi bạn nạp đầy hàng đợi. Điều này có thể hữu ích khi xử lý một trình tạo số ngẫu nhiên an toàn hơn là Randomlớp thông thường .
Joe Enos

2
@JoeEnos MS sai lầm thực hiện NextBytes, do đó, nó đáng ngạc nhiên chậm
CodesInChaos

1
@CodesInChaos Chà, thật thú vị - Tôi vừa tra cứu nó trong một trình tháo gỡ để xem bạn đang đề cập đến điều gì: buffer[i] = (byte)(this.InternalSample() % 256);- Tôi cho rằng đó là những gì bạn đang nói, rằng họ có thể đã lấy số nguyên ngẫu nhiên đó và chia nó thành 3 byte , điền mảng byte với khoảng 1/3 công việc. Tôi tự hỏi liệu có lý do cho điều đó hay đó chỉ là sự giám sát của các nhà phát triển.
Joe Enos

Câu trả lời:


72

Các tùy chọn đầu tiên - rand.Next(2)thực thi đằng sau hậu trường đoạn mã sau:

if (maxValue < 0)
{
    throw new ArgumentOutOfRangeException("maxValue",
        Environment.GetResourceString("ArgumentOutOfRange_MustBePositive", new object[] { "maxValue" }));
}
return (int) (this.Sample() * maxValue);

và đối với tùy chọn thứ hai - rand.NextDouble():

return this.Sample();

Vì tùy chọn đầu tiên chứa maxValuexác nhận, nhân và ép, tùy chọn thứ hai có thể nhanh hơn .


Cảm ơn bạn, đó là tất cả những gì tôi muốn biết.
hẹn giờ

5
Thời gian của riêng tôi nói rằng tùy chọn thứ hai nhanh hơn khoảng 5% so với tùy chọn đầu tiên.
ClickRick

60

Cải tiến nhỏ cho tùy chọn thứ hai :

Theo MSDN

public virtual double NextDouble()

trả lại

Số dấu phẩy động có độ chính xác kép lớn hơn hoặc bằng 0,0 và nhỏ hơn 1,0.

Vì vậy, nếu bạn muốn một bool ngẫu nhiên trải đều, bạn nên sử dụng >= 0.5

rand.NextDouble() >= 0.5

Phạm vi 1: [0.0 ... 0.5 [
Phạm vi 2: [0.5 ... 1.0 [
| Phạm vi 1 | = | Dãy 2 |


9

Nhanh nhất. Gọi phương thức Random.Nextcó chi phí thấp hơn. Phương thức mở rộng bên dưới chạy nhanh hơn 20% và nhanh hơn Random.NextDouble() > 0.535% Random.Next(2) == 0.

public static bool NextBoolean(this Random random)
{
    return random.Next() > (Int32.MaxValue / 2);
    // Next() returns an int in the range [0..Int32.MaxValue]
}

Nhanh hơn nhanh nhất. Có thể tạo các boolean ngẫu nhiên với Randomlớp nhanh hơn bằng cách sử dụng các thủ thuật. 31 bit quan trọng của một được tạo intcó thể được sử dụng cho 31 lần sản xuất boolean tiếp theo. Việc triển khai bên dưới nhanh hơn 40% so với cách được tuyên bố trước đó là nhanh nhất.

public class RandomEx : Random
{
    private uint _boolBits;

    public RandomEx() : base() { }
    public RandomEx(int seed) : base(seed) { }

    public bool NextBoolean()
    {
        _boolBits >>= 1;
        if (_boolBits <= 1) _boolBits = (uint)~this.Next();
        return (_boolBits & 1) == 0;
    }
}

Cảm ơn! Đối với những người sử dụng UnityEngine để viết script, hãy đảm bảo sử dụng System.Random chứ không phải UnityEngine.Random, vì chúng không giống nhau!
DonCarleone

6

Tôi đã chạy thử nghiệm với đồng hồ bấm giờ. 100.000 lần lặp:

System.Random rnd = new System.Random();
if (rnd.Next(2) == 0)
     trues++;

CPU thích số nguyên, vì vậy phương pháp Next (2) nhanh hơn. 3.700 so với 7.500 mili giây, khá là đáng kể. Ngoài ra: Tôi nghĩ rằng các số ngẫu nhiên có thể là một nút thắt cổ chai, tôi đã tạo khoảng 50 mỗi khung hình trong Unity, ngay cả với một cảnh nhỏ làm chậm hệ thống của tôi một cách đáng kể, vì vậy tôi cũng hy vọng tìm ra phương pháp để tạo ra một bool ngẫu nhiên. Vì vậy tôi cũng đã thử

if (System.DateTime.Now.Millisecond % 2 == 0)
       trues++;

nhưng việc gọi một hàm tĩnh thậm chí còn chậm hơn với 9.600ms. Đáng để thử. Cuối cùng, tôi đã bỏ qua phép so sánh và chỉ tạo 100.000 giá trị ngẫu nhiên, để đảm bảo rằng phép so sánh int và gấp đôi không ảnh hưởng đến thời gian đã trôi qua, nhưng kết quả là khá giống nhau.


1
DateTime.Now nổi tiếng là chậm. Tốt nhất nên sử dụng các giải pháp phụ thuộc vào phần cứng hoặc ít nhất là phụ thuộc vào hệ điều hành để làm cho nó nhanh chóng.
Do-do-new

Sử dụng DateTime.UtcNow, nó là nhanh hơn nhiều DateTime.Now.
Theodor Zoulias
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.