I need to quickly generate random floating-point numbers across multiple running threads. I\'ve tried using System.Random, but it\'s too slow for my needs and it re
I use the windows cryptoAPI for good random numbers. For performance I do a single call for a block of 8KB of random data and distribute numbers from that instead of call the cryptoAPI for each number. Not sure what the performance is in the end compared to the normal random. But the randomization is far better (check the internet for details on the Windows CryptoAPI)
This is the code;
// UNIT RandomNumberGeneratorBase
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace FastLibrary
{
public abstract class RandomNumberGeneratorBase
{
private int _byteBufSize;
private byte[] _buf;
private int _idx;
private int _lastsize;
public RandomNumberGeneratorBase(int bufSize = 8092)
{
_byteBufSize = bufSize;
_buf = new byte[_byteBufSize];
_idx = _byteBufSize;
}
protected abstract void GetNewBuf(byte[] buf);
private void CheckBuf(int bytesFreeNeeded = 1)
{
_idx += _lastsize;
_lastsize = bytesFreeNeeded;
if (_idx + bytesFreeNeeded < _byteBufSize) { return; }
GetNewBuf(_buf);
_idx = 0;
}
public byte GetRandomByteStartAtZero(int belowValue)
{
return (byte)(Math.Round(((double)GetRandomByte() * (belowValue - 1)) / 255));
}
public int GetRandomIntStartAtZero(int belowValue)
{
return (int)(Math.Round(((double)GetRandomUInt32() * (double)(belowValue - 1)) / (double)uint.MaxValue));
}
public byte GetRandomByte()
{
CheckBuf();
return _buf[_idx];
}
public bool GetRandomBool()
{
CheckBuf();
return _buf[_idx] > 127;
}
public ulong GetRandomULong()
{
CheckBuf(sizeof(ulong));
return BitConverter.ToUInt64(_buf, _idx);
}
public int GetRandomInt()
{
CheckBuf(sizeof(int));
return BitConverter.ToInt32(_buf, _idx);
}
///
/// Double from 0 to 1 (might be zero, will never be 1)
///
public double GetRandomDouble()
{
return GetRandomUInt32() / (1d + UInt32.MaxValue);
}
///
/// Float from 0 to 1 (might be zero, will never be 1)
///
public float GetRandomFloat()
{
return GetRandomUInt32() / (1f + UInt32.MaxValue);
}
public uint GetRandomUInt32()
{
CheckBuf(sizeof(UInt32));
return BitConverter.ToUInt32(_buf, _idx);
}
}
}
// UNIT StrongRandomNumberGenerator
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
namespace FastLibrary
{
public sealed class StrongRandomNumberGenerator : RandomNumberGeneratorBase
{
private RNGCryptoServiceProvider _rnd;
public StrongRandomNumberGenerator()
{
_rnd = new RNGCryptoServiceProvider();
}
protected override void GetNewBuf(byte[] buf)
{
_rnd.GetBytes(buf);
}
}
}