我想得到1到0之间的随机数.但是,我每次都得到0.有人可以解释我为什么一直都是0的原因吗?这是我试过的代码.
Random random = new Random();
int test = random.Next(0, 1);
Console.WriteLine(test);
Console.ReadKey();
Run Code Online (Sandbox Code Playgroud)
Gol*_*den 16
根据文档,Next返回(包括)最小值和(不包括)最大值之间的整数随机数:
回报价值
大于或等于minValue且小于maxValue的32位有符号整数; 也就是说,返回值的范围包括minValue但不包括maxValue.如果minValue等于maxValue,则返回minValue.
唯一满足的整数
0 <= x < 1
Run Code Online (Sandbox Code Playgroud)
是0,因此你总是得到价值0.换句话说,0是半闭区间内唯一的整数[0, 1).
所以,如果你真的对整数值感兴趣,0或者1使用2上限:
var n = random.Next(0, 2);
Run Code Online (Sandbox Code Playgroud)
如果您希望获得0到1之间的小数,请尝试:
var n = random.NextDouble();
Run Code Online (Sandbox Code Playgroud)
希望这可以帮助 :-)
您可以,但是您应该这样做:
double test = random.NextDouble();
Run Code Online (Sandbox Code Playgroud)
如果要获取随机整数(0或1),则应将上限设置为2,因为它是互斥的
int test = random.Next(0, 2);
Run Code Online (Sandbox Code Playgroud)
此页面上有关双打的每个答案都是错误的,这很有趣,因为每个人都在引用文档。如果使用NextDouble()生成双精度数,则不会得到0到1之间(包括1)的数字,而不会得到0到1之间的数字(不包括1)。
要获得双倍奖励,您将需要执行以下操作:
public double NextRandomRange(double minimum, double maximum)
{
Random rand = new Random();
return rand.NextDouble() * (maximum - minimum) + minimum;
}
Run Code Online (Sandbox Code Playgroud)
然后打电话
NextRandomRange(0,1 + Double.Epsilon);
Run Code Online (Sandbox Code Playgroud)
似乎可行,不是吗?1 + Double.Epsilon在使用double时应该是1之后的第二大数字,对吗?这是解决int问题的方法。
Wellllllllllllllll .........
我怀疑这将无法正常工作,因为基础代码将生成一些字节的随机性,然后执行一些数学技巧以使其符合预期范围。简短的答案是,适用于int的逻辑在使用浮点数时效果并不完全相同。
让我们看看,好吗?(https://referencesource.microsoft.com/#mscorlib/system/random.cs,e137873446fcef75)
/*=====================================Next=====================================
**Returns: A double [0..1)
**Arguments: None
**Exceptions: None
==============================================================================*/
public virtual double NextDouble() {
return Sample();
}
Run Code Online (Sandbox Code Playgroud)
Sample()到底是什么?
/*====================================Sample====================================
**Action: Return a new random number [0..1) and reSeed the Seed array.
**Returns: A double [0..1)
**Arguments: None
**Exceptions: None
==============================================================================*/
protected virtual double Sample() {
//Including this division at the end gives us significantly improved
//random number distribution.
return (InternalSample()*(1.0/MBIG));
}
Run Code Online (Sandbox Code Playgroud)
好吧,开始到某个地方。MBIG btw是Int32.MaxValue(2147483647或2 ^ 31-1),使除法运算为:
InternalSample()*0.0000000004656612873077392578125;
Run Code Online (Sandbox Code Playgroud)
好吧,InternalSample()到底是什么?
private int InternalSample() {
int retVal;
int locINext = inext;
int locINextp = inextp;
if (++locINext >=56) locINext=1;
if (++locINextp>= 56) locINextp = 1;
retVal = SeedArray[locINext]-SeedArray[locINextp];
if (retVal == MBIG) retVal--;
if (retVal<0) retVal+=MBIG;
SeedArray[locINext]=retVal;
inext = locINext;
inextp = locINextp;
return retVal;
}
Run Code Online (Sandbox Code Playgroud)
好吧...那是什么。但是,这个SeedArray和inext废话到底是什么?
private int inext;
private int inextp;
private int[] SeedArray = new int[56];
Run Code Online (Sandbox Code Playgroud)
所以事情开始融为一体。种子数组是一个整数数组,用于从中生成值。如果您看一下init函数def,您会发现要进行大量的位加法运算和欺骗操作,以使55个值的数组与初始准随机值随机化。
public Random(int Seed) {
int ii;
int mj, mk;
//Initialize our Seed array.
//This algorithm comes from Numerical Recipes in C (2nd Ed.)
int subtraction = (Seed == Int32.MinValue) ? Int32.MaxValue : Math.Abs(Seed);
mj = MSEED - subtraction;
SeedArray[55]=mj;
mk=1;
for (int i=1; i<55; i++) { //Apparently the range [1..55] is special (All hail Knuth!) and so we're skipping over the 0th position.
ii = (21*i)%55;
SeedArray[ii]=mk;
mk = mj - mk;
if (mk<0) mk+=MBIG;
mj=SeedArray[ii];
}
for (int k=1; k<5; k++) {
for (int i=1; i<56; i++) {
SeedArray[i] -= SeedArray[1+(i+30)%55];
if (SeedArray[i]<0) SeedArray[i]+=MBIG;
}
}
inext=0;
inextp = 21;
Seed = 1;
}
Run Code Online (Sandbox Code Playgroud)
好的,回到InternalSample(),我们现在可以看到,通过取两个加扰的32位整数的差,将结果限制在0到2147483647-1之间,然后将结果乘以1,可以生成随机双精度数。 2147483647。在使用种子值时,要花更多的时间来加扰种子值列表,但实际上就是这样。
(有趣的是,获得2到31-2范围内任何数字的机会大约是1 / r,即2 *(1 / r)!因此,如果您认为某些dumbass编码器正在使用RandNext( )在视频扑克机上生成数字,您应该始终下注2 ^ 32-2!这就是为什么我们不将Random用作重要内容的原因之一...)
因此,如果InternalSample()的输出为0,则将其乘以0.0000000004656612873077392578125并得到0,即我们范围的底端。如果我们得到2147483646,我们最终得到0.9999999995343387126922607421875,那么NextDouble产生[0,1)结果的说法是...对吗?可以更准确地说是[0,0.9999999995343387126922607421875]的范围。
由于double.Epsilon = 4.94065645841247E-324,它比0.0000000004656612873077392578125(您要加到上面的结果中得到的数量为1的方式)小,因此我建议的上述解决方案将落在它的脸上。
具有讽刺意味的是,如果不是要在InternalSample()方法中减去一个:
if (retVal == MBIG) retVal--;
Run Code Online (Sandbox Code Playgroud)
我们可以将返回的返回值设为1。因此,要么复制Random类中的所有代码,然后省略retVal--行,要么将NextDouble()输出乘以1.0000000004656612612875245796924106之类的值,以稍微拉伸输出范围以使其包含1。实际上,测试该值可以使我们真正接近,但我不知道我进行的几亿次测试是否没有产生2147483646(很有可能)或方程中是否存在浮点误差。我怀疑前者。数百万次测试不太可能产生20亿分之一的赔率。
NextRandomRange(0,1.0000000004656612875245796924106); // try to explain where you got that number during the code review...
Run Code Online (Sandbox Code Playgroud)
TLDR?随机双打的包容范围非常棘手...