Algorithm 如何使用random()={0..1}生成任意范围内的数字,以保持一致性和密度?
在[x..y]范围内生成一个随机数,其中x和y是任意浮点数。使用函数random(),它从P个均匀分布的数字(称之为“密度”)返回范围为[0..1]的随机浮点数。必须保持均匀分布,P也必须缩放 我认为,解决这样的问题是不容易的。为了简化一点,我问你们如何在区间[-0.5..0.5],然后在[0..2],然后在[-2..0]中生成一个数字,保持一致性和密度?因此,对于[0..2],它必须从P*2均匀分布的数字生成一个随机数Algorithm 如何使用random()={0..1}生成任意范围内的数字,以保持一致性和密度?,algorithm,random,entropy,Algorithm,Random,Entropy,在[x..y]范围内生成一个随机数,其中x和y是任意浮点数。使用函数random(),它从P个均匀分布的数字(称之为“密度”)返回范围为[0..1]的随机浮点数。必须保持均匀分布,P也必须缩放 我认为,解决这样的问题是不容易的。为了简化一点,我问你们如何在区间[-0.5..0.5],然后在[0..2],然后在[-2..0]中生成一个数字,保持一致性和密度?因此,对于[0..2],它必须从P*2均匀分布的数字生成一个随机数 显而易见的简单解决方案random()*(x-y)+y不会生成所有可能的数
显而易见的简单解决方案
random()*(x-y)+y
不会生成所有可能的数字,因为所有abs(x-y)>1.0
案例的密度都较低。许多可能的值将被忽略。记住,random()只返回P个可能数中的一个数。然后,如果你把这个数乘以Q,它只会给你一个P可能值,按Q缩放,但你也必须按Q缩放密度P。如果我理解你的问题,我会给你一个解决方案:但我会从范围中排除1
N = numbers_in_your_random // [0, 0.2, 0.4, 0.6, 0.8] will be 5
// This turns your random number generator to return integer values between [0..N[;
function randomInt()
{
return random()*N;
}
// This turns the integer random number generator to return arbitrary
// integer
function getRandomInt(maxValue)
{
if (maxValue < N)
{
return randomInt() % maxValue;
}
else
{
baseValue = randomInt();
bRate = maxValue DIV N;
bMod = maxValue % N;
if (baseValue < bMod)
{
bRate++;
}
return N*getRandomInt(bRate) + baseValue;
}
}
// This will return random number in range [lower, upper[ with the same density as random()
function extendedRandom(lower, upper)
{
diff = upper - lower;
ndiff = diff * N;
baseValue = getRandomInt(ndiff);
baseValue/=N;
return lower + baseValue;
}
N=numbers\u在您的\u random/[0,0.2,0.4,0.6,0.8]中将为5
//这将使随机数生成器返回[0..N[]之间的整数值;
函数randomInt()
{
返回random()*N;
}
//这将使整数随机数生成器返回任意值
//整数
函数getRandomInt(maxValue)
{
如果(最大值
好吧,[0..1]*2==[0..2]
(仍然统一)
[0..1]-0.5==[-0.5..0.5]
等
我想知道你在哪里经历过这样的面试
更新:好吧,如果我们想开始关心乘法精度的降低(这很奇怪,因为在最初的任务中,不知何故你并不关心这个问题,而假装我们关心“值的数量”,我们可以开始迭代。为此,我们还需要一个函数,它将返回[0..1]中均匀分布的随机值
-这可以通过删除1.0
值来完成。之后,我们可以将整个范围切成足够小的等分,不必担心精度下降,随机选择一个(我们有足够的随机性),并使用[0..1]函数为所有部分选择一个数字,但最后一个部分除外
或者,您可以想出一种方法来编码足够多的值,只需为代码生成随机位,在这种情况下,您并不真正关心它是[0..1]还是{0,1}。在真实数学中:解决方案就是提供的:
return random() * (upper - lower) + lower
问题是,即使有浮点数,也只有一定的分辨率。因此,您可以应用上述函数并添加另一个按比例缩放到缺失部分的random()值
如果我举一个实际的例子,我的意思就会变得很清楚:
例如,取0..1中的random()返回值,精度为2位,即0.XY,下限为100,上限为1100
使用上述算法,得到的结果是0.XY*(1100-100)+100=XY0.0+100。
您永远不会看到结果是201,因为最后一个数字必须是0
这里的解决方案是再次生成一个随机值并将其加上*10,这样你就有了一位数的精度(这里你必须注意不要超过给定的范围,这可能会发生,在这种情况下,你必须放弃结果并生成一个新的数)
也许您必须重复它,重复的频率取决于random()函数提供了多少个位置,以及您对最终结果的期望值
在标准IEEE格式中,精度有限(即双53位)。因此,当您以这种方式生成一个数字时,您永远不需要生成多个额外的数字
但你必须小心,当你添加新的数字时,你不会超过给定的上限。有多种解决方案:首先,如果你超过了上限,你从新开始,生成一个新的数字(不要切断或类似,因为这会改变分布)
第二种可能性是检查丢失的低位范围的间隔大小,以及
找到中间值,并生成一个合适的值,保证结果是合适的。 < P>你必须考虑从每个调用到RNG的熵量。这里有一些我刚写的C代码,说明了如何从低熵源中积累熵,最后以高熵随机值结束。
using System;
using System.Collections.Generic;
using System.Security.Cryptography;
namespace SO_8019589
{
class LowEntropyRandom
{
public readonly double EffectiveEntropyBits;
public readonly int PossibleOutcomeCount;
private readonly double interval;
private readonly Random random = new Random();
public LowEntropyRandom(int possibleOutcomeCount)
{
PossibleOutcomeCount = possibleOutcomeCount;
EffectiveEntropyBits = Math.Log(PossibleOutcomeCount, 2);
interval = 1.0 / PossibleOutcomeCount;
}
public LowEntropyRandom(int possibleOutcomeCount, int seed)
: this(possibleOutcomeCount)
{
random = new Random(seed);
}
public int Next()
{
return random.Next(PossibleOutcomeCount);
}
public double NextDouble()
{
return interval * Next();
}
}
class EntropyAccumulator
{
private List<byte> currentEntropy = new List<byte>();
public double CurrentEntropyBits { get; private set; }
public void Clear()
{
currentEntropy.Clear();
CurrentEntropyBits = 0;
}
public void Add(byte[] entropy, double effectiveBits)
{
currentEntropy.AddRange(entropy);
CurrentEntropyBits += effectiveBits;
}
public byte[] GetBytes(int count)
{
using (var hasher = new SHA512Managed())
{
count = Math.Min(count, hasher.HashSize / 8);
var bytes = new byte[count];
var hash = hasher.ComputeHash(currentEntropy.ToArray());
Array.Copy(hash, bytes, count);
return bytes;
}
}
public byte[] GetPackagedEntropy()
{
// Returns a compact byte array that represents almost all of the entropy.
return GetBytes((int)(CurrentEntropyBits / 8));
}
public double GetDouble()
{
// returns a uniformly distributed number on [0-1)
return (double)BitConverter.ToUInt64(GetBytes(8), 0) / ((double)UInt64.MaxValue + 1);
}
public double GetInt(int maxValue)
{
// returns a uniformly distributed integer on [0-maxValue)
return (int)(maxValue * GetDouble());
}
}
class Program
{
static void Main(string[] args)
{
var random = new LowEntropyRandom(2); // this only provides 1 bit of entropy per call
var desiredEntropyBits = 64; // enough for a double
while (true)
{
var adder = new EntropyAccumulator();
while (adder.CurrentEntropyBits < desiredEntropyBits)
{
adder.Add(BitConverter.GetBytes(random.Next()), random.EffectiveEntropyBits);
}
Console.WriteLine(adder.GetDouble());
Console.ReadLine();
}
}
}
}
使用系统;
使用System.Collections.Generic;
使用System.Security.Cryptography;
名称空间SO_8019589
{
LowEntropyRandom类
{
公共只读双效PropBybits;
公共只读int-PossibleOutcomeCount;
私有只读双间隔;
private readonly Random=new Random();
公共LowEntropyRandom(int possibleotComount)
{
PossibleOutcomeCount=PossibleOutcomeCount;
EffectiveEntropyBits=Math.Log(可能是eoutcomeCount,2);
间隔=1.0/可能的平均计数;
}
公共LowEntropyRandom(int-PossibleoutComCount,int-seed)
:此(可能为EOUTCOUNT)
{
随机=新随机(种子);
}
公共int Next()
{
返回random.Next(PossibleOutcomeCount);
}
公共双下位双工(
( random() * (Y-X) + X ) + ( random() / 10 ^ (PREC-trunc(lg(Y-X))) )
( random() * (1500-500) + 500 ) + ( random() / 10 ^ (20-trunc(lg(1000))) )
( random() * 1000 + 500 ) + ( random() / 10 ^ (17) )
- 0.4663164 -> PREC=7
- 0.2581916 -> PREC=7
- 0.9147385 -> PREC=7
- 0.129141 -> PREC=6 -> 7, correcting by the average of the other tries
randomBit() { return random() >= 0.5; }
randomInt(N) { while ((val = random2(ceil(log2(N)))) >= N); return val; }
rand2D(N) { return random2(N) + random(); }
randD(V) { while ((val = rand2D(ceil(log2(V)))) >= V); return val; }
rand(L, U) { return L + randD(U - L); }
const p;
function rand(x, y)
r = random()
if y-x <= 1
return x + r*(y-x)
else
low = r*(p-1)*(y-x)/p
high = low + (y-x)/p
return x + low + rand(low, high)