我试图在C#中为一个科学项目获得一个随机的bool。问题是布尔值为真的几率必须在10 ^ -12到10 ^ -14之间;默认随机函数只生成整数,0和[u]之间的值int.max远小。
如何生成一个随机布尔值,其真实可能性很小?
答案 0 :(得分:15)
编辑
正如Kyle在下面的评论中建议的那样,Random.NextDouble()
的实施将int
映射到区间[0.0,1.0],有效地使我的代码等同于r.Next( 0, Int32.MaxValue ) == 0
。添加更多的零不会影响结果为假的概率。
使用其他答案之一,或使用此代码从System.Random
生成ulong(范围0-18446744073709551615)。
var r = new Random();
var bytes = new byte[8];
r.NextBytes(bytes);
ulong result = BitConverter.ToUInt64(bytes, 0);
警告:无法按预期工作,请勿使用!仅为上下文提供。
改为使用Random.NextDouble()
:结果是介于0.0和1.0之间的双倍
var r = new Random();
var probablyFalseBool = r.NextDouble() < 0.0000000000001;
如有必要,可以改变零的数量。
答案 1 :(得分:15)
尝试组合多个随机选择:
if(rnd.Next(0,10000) == 0 && rnd.Next(0,10000) == 0 && rnd.Next(0,10000) == 0){
}
不确定C#语法是否正确,但是输入if块的概率为10 ^ -12。
答案 2 :(得分:3)
您可以使用NextBytes
方法获取较大的随机数。
例如,这将给出2.842e-14概率,即布尔值为true
:
Random r = new Random();
byte[] buffer = new byte[6]; // make an array with 48 bits
r.NextBytes(buffer);
buffer[0] &= 0xf8; // mask out three bits to make it 45
bool occured = buffer.Sum(b => b) == 0;
答案 3 :(得分:2)
正如Nathan建议的那样,您可以使用Next
方法指定结果范围。
然后,您可以使用&&
运算符来确保它符合您的精确度。
// 1 in a million
var result = random.Next(0, 1000) == 0 && random.Next(0, 1000) == 0;
然后您可以更改它们以获得所需的费率。
答案 4 :(得分:1)
您可以轻松控制这样的几率:
var result = rnd.Next(0,100) == 0;
这样可以使result
的赔率为真100分。您可以轻松地将值调整到您想要的任何赔率。
答案 5 :(得分:1)
多维度!正常的随机数是单个维度(即沿着一条线)。通过将两个随机数相乘,您将使用两个维度,依此类推。
如果你取1到100之间的6个随机整数,那么将它们相乘得到结果1的概率是10 ^ 12中的1。与1到1000之间的4个随机整数相同,或者1到10000之间的3个随机整数。
如果您想要10 ^ 12中的30,那么请使用1到1,000,000之间的两个随机数,并且您希望一个为1而另一个为30或更少。
如果您想要10 ^ 12中的x(<1,000,000),那么请使用介于1和1,000,000之间的两个随机数,并且您希望一个为1而另一个为x或更小。
答案 6 :(得分:0)
连续生成两个整数,表示
(target_value div int_max, target_value mod int_max)
选中较大的0
,第二个小于desired_precison * int_max
。
如果您对引入偏差有疑问,请在测试前将两个整数的顺序随机化。
此独立代码说明了该技术(已测试here):
using System.IO;
using System;
class Program
{
static void Main(string[] args)
{
bool flip, strike;
int eps, lo, hi;
Random rnd;
eps = Int32.Parse(args[0]); // whatever is appropriate
rnd = new Random();
lo = rnd.Next(Int32.MaxValue);
hi = rnd.Next(Int32.MaxValue);
flip = (rnd.Next() > 0.5);
if (flip) { int swap; swap = lo; lo = hi; hi = swap; }
strike = (hi == 0) && (lo < eps);
Console.Write("[hi lo] = ");
Console.Write(hi);
Console.WriteLine(lo);
if (strike) {
Console.WriteLine("strike");
}
}
}
答案 7 :(得分:0)
而不是Round.Next
,您可以使用Round.NextDouble或Round.NextBytes来获得更广泛的范围。
使用NextBytes
,您可以使用4-5字节的缓冲区来获得所需的范围。非常粗略,你可以这样做:
var buffer=new byte[5];
rnd.NextBytes(buffer);
return buffer.All(b=>b>0);
您可以使用BitArray
加快速度使用NextDouble
,您需要检查结果是否小于1/10 ^ 12.