임의의 부울을 생성하는 가장 빠른 방법


87

따라서 C #에서 임의의 부울을 만드는 방법에는 여러 가지가 있습니다.

  • Random.Next () 사용 : rand.Next(2) == 0
  • Random.NextDouble () 사용 : rand.NextDouble() > 0.5

정말 차이가 있습니까? 그렇다면 실제로 어떤 것이 더 나은 성능을 가지고 있습니까? 아니면 내가 보지 못한 다른 방법이 있습니까? 더 빠를 수 있습니까?



7
이것이 정말로 병목 현상입니까?
Brian Rasmussen 2013 년

2
실제로 실행하지 않고 (어떤 방법도 터무니없이 빠르기 때문에), 내 추측은 NextBytes바이트 배열을 미리 채우고, 그것을 BitArray부울 컬렉션으로 바꾸는 데 사용 하고, Queue비울 때까지 그 부울을 검색 한 다음 반복하는 것입니다. 과정. 이 방법을 사용하면 Randomizer를 한 번만 사용하므로 생성되는 오버 헤드는 대기열을 다시 채울 때만 발생합니다. 이것은 일반 Random클래스가 아닌 보안 난수 생성기를 다룰 때 유용 할 수 있습니다 .
Joe Enos

2
@JoeEnos MS는의 구현을 엉망 NextBytes이 놀라 울 정도로 느린, 그래서
CodesInChaos

1
와우 @CodesInChaos, 그 흥미 롭군요 - 난 그냥 당신이 언급 된 것을 볼 수 디스어셈블러에서 그것을 보았다 : buffer[i] = (byte)(this.InternalSample() % 256);- 나는 당신이 그들이 3 바이트에이를 임의의 정수 않도록주의하고 분할 한 수에 대한 말을하는지입니다 있으리라 믿고있어 , 작업의 약 1/3로 바이트 배열을 채 웁니다. 그 이유가 있었는지 아니면 개발자의 감독 이었는지 궁금합니다.
Joe Enos

답변:


72

번째 옵션 - rand.Next(2)뒤에서 다음 코드를 실행합니다.

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

과에 대한 두 번째 옵션 - rand.NextDouble():

return this.Sample();

첫 번째 옵션에는 maxValue유효성 검사, 곱셈 및 캐스팅이 포함되어 있으므로 두 번째 옵션이 더 빠를 것 입니다.


감사합니다. 그게 제가 알고 싶었던 전부입니다.
timedt 2010 년

5
내 자신의 타이밍에 따르면 두 번째 옵션은 첫 번째 옵션보다 약 5 % 빠릅니다.
ClickRick

60

두 번째 옵션에 대한 작은 향상 :

MSDN 에 따르면

public virtual double NextDouble()

보고

0.0보다 크거나 같고 1.0보다 작은 배정 밀도 부동 소수점 숫자입니다.

따라서 균등하게 퍼진 임의의 bool을 원한다면 >= 0.5

rand.NextDouble() >= 0.5

범위 1 : [0.0 ... 0.5 [
범위 2 : [0.5 ... 1.0 [
| 범위 1 | = | 범위 2 |


9

가장 빠른. 메서드 Random.Next를 호출하면 오버 헤드가 적습니다. 확장 방법은 20 % 이하로보다 빠른 실행 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]
}

가장 빠른 것보다 빠릅니다. Random트릭을 사용하여 클래스 와 함께 임의의 부울을 더 빠르게 생성 할 수 있습니다 . 생성 된 31 개의 중요한 비트는 int31 개의 후속 부울 생성에 사용될 수 있습니다. 아래 구현은 이전에 가장 빠른 것으로 선언 된 것보다 40 % 더 빠릅니다.

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;
    }
}

감사! UnityEngine을 사용하여 스크립트를 작성하는 경우 UnityEngine.Random이 아닌 System.Random을 사용해야합니다. 동일하지 않기 때문입니다!
DonCarleone

6

스톱워치로 테스트를 진행했습니다. 100,000 회 반복 :

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

CPU는 정수와 같으므로 Next (2) 메서드가 더 빠릅니다. 3,700 대 7,500ms는 상당히 큽니다. 또한 난수는 병목 현상이 될 수 있다고 생각합니다. 시스템 속도가 눈에 띄게 느려지는 작은 장면에서도 Unity에서 약 50 개의 프레임을 만들었 기 때문에 임의의 부울을 만드는 방법도 찾고 싶었습니다. 그래서 나는 또한 시도했다

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

그러나 정적 함수 호출은 9,600ms로 더 느 렸습니다. 한 번의 가치가 있습니다. 마지막으로 비교를 건너 뛰고 100,000 개의 임의 값만 생성하여 int 대 이중 비교가 경과 시간에 영향을주지 않았는지 확인했지만 결과는 거의 동일했습니다.


1
DateTime.Now는 매우 느립니다. 이상적으로는 하드웨어 의존적 솔루션 또는 최소한 OS 의존적 솔루션을 사용하여 신속하게 처리해야합니다.
Do-do-new

을 사용 DateTime.UtcNow하면보다 훨씬 빠릅니다 DateTime.Now.
Theodor Zoulias 19
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.