C#最快的方式随机索引到一个数组
-
18-09-2019 - |
题
我有双值“瓦尔斯”的阵列,我需要随机索引到该阵列和得到的值。 GenRandomNumber()返回0和1,但从来没有0或1。我使用Convert.ToInt32基本上得到一切我小数点左边,但必须有这样做的更有效的方法之间的一个数字?
下面是我的代码:
public double GetRandomVal()
{
int z = Convert.ToInt32(GenRandomNumber() * (vals.Length));
return vals[z];
}
由于
更新
感谢所有那些谁回答,但我不得不使用具有方法所提供的梅森旋转算法的随机数实施rand.NextDouble()
<强>更新2 强>
了解这个一些更多的思考,所有我需要做的是的根的随机数之间的0和array.length-1,然后使用该随机索引到阵列即可。瓦尔斯长度为2 ^ 20 = 1048576所以产生随机int是足够的。我发现我的梅森旋转算法有一个方法:
public int Next(int maxValue)
如果我称之为例如瓦尔斯[rand.Next(vals.length-1)] 强>应该这样做正确?我还看到梅森旋转算法有一个构造:
public MersenneTwister(int[] init)
不知道这是用于,我可以使用该预填充的可接受的随机数为我提供的0阵列以vals.length?
FYI瓦尔斯是长度1048576的双阵列划分正态分布曲线。我基本上是用这种机制来尽可能快地创建正态分布的号码,在蒙特卡洛模拟使用了数十亿正态分布随机数的每一天所以每一点帮助。
解决方案
尝试使用一个随机整数代替:
Random random = new Random();
int randomNumber = random.Next(0, vals.Length);
return vals[randomNumber];
其他提示
return vals[rng.Next(vals.Length)];
其中RNG是
Random rng = new Random();
我想你已经确定了最简单最直接的实现。
但是,如果你正在寻找您的随机索引算法的性能提升,你可以只是“的破解的”的IEEE 754编码的双入其指数和分数 - 并使用分数取模阵列尺寸为随机索引。
此技术也不太可能是加密的安全 - 所以如果这是一个考虑因素 - 不这样做。
此外,这种方法的不的使代码更明显 - 我会坚持你最初的实现,除非最大限度地提高性能的考虑。顺便说一句,该处理最慢的部分是最有可能的Mersenne扭曲产生的随机数。
下面的代码:
[StructLayout(LayoutKind.Explicit)] // used create a union of Long and Double
public struct IEEE754
{
private const ulong SIGN_BITS = 0x8000000000000000;
private const ulong EXPONENT_BITS = 0x7FF0000000000000;
private const ulong FRACTION_BITS = 0x000FFFFFFFFFFFFF;
private const int SIGN_OFFSET = 63;
private const int EXPONENT_OFFSET = 52;
// [FieldOffset] attribute is .NET's way of defining how to explicitly
// layout the fields of a structure - we're using it to overlay the
// double and long into a single bit-space ... effectively a C# 'union'
[FieldOffset( 0 )] private double DoubleValue;
[FieldOffset( 0 )] private ulong LongValue;
public IEEE754(double val)
{
DoubleValue = val;
}
// properties that retrieve the various pieces of an IEEE754 double
public long Fraction { get { return (long)(LongValue & FRACTION_BITS); } }
public long Exponent { get { return (long)((LongValue & EXPONENT_BITS) >> EXPONENT_OFFSET); } }
public long Sign { get { return (long)((LongValue & SIGN_BITS) >> SIGN_OFFSET); } }
public void Set( double val ) { DoubleValue = val; }
}
public static void TestFunction()
{
var array = Enumerable.Range( 1, 10000 ).ToArray(); // test array...
// however you access your random generator would go here...
var rand = new YourRandomNumberGenerator();
// crack the double using the special union structure we created...
var dul = new IEEE754( rand.GenRandomNumber() );
// use the factional value modulo the array length as a random index...
var randomValue = array[dul.Fraction % array.Length];
}
你有没有使用.NET Random类考虑?
我会使用 Random.Next(Int32)已,该返回比输入和> =零以下的值。通过你的数组长度作为输入,并且你已经有了一个随机有效的索引。
至于其他人已经指出,System.Random具有过载接下来会做什么你问了。
至于你对Convert.ToInt32
和更有效的替代评论,你可以直接投出double
到int
:
double d = 1.5;
int i = (int)d;
private static readonly Random _random = new Random();
public double GetRandomVal()
{
int z = _random.Next(vals.Length);
return vals[z];
}
如果你不约束使用您的随机函数,使用Random
类。
public Double GetRandomValue(Double[] values)
{
return values[new Random().Next(values.Length)];
}
否则我只想用一个造型,因为它给出了正确的行为 - 趋向于零,而不是最接近的整数Convert.ToInt32()
做四舍五入
public Double GetRandomValue(Double[] values)
{
return values[(Int32)(GetNextRandomNumber() * values.Length)];
}