标题几乎说明了一切。当然,我知道我可以使用Random.NextInt()
,但我想知道是否有办法将无界随机数据转化为有界而无统计偏差。 (这意味着没有RandomInt() % (maximum-minimum)) + minimum
)。当然有一种类似的方法,它不会在输出的数据中引入偏差吗?
答案 0 :(得分:2)
如果您认为这些位是随机分布的,我建议:
n
是位数使用所需的位数是实现这一目标的关键 - 你可以丢弃最多一半的字节数,但不会超过这个数,假设分布良好。 (如果你在一个很好的二进制范围内生成数字,你将不需要扔掉任何东西。)
实施作为练习留给读者:)
答案 1 :(得分:1)
您可以尝试使用以下内容:
public static int MyNextInt(Random rnd, int minValue, int maxValue)
{
var buffer = new byte[4];
rnd.NextBytes(buffer);
uint num = BitConverter.ToUInt32(buffer, 0);
// The +1 is to exclude the maxValue in the case that
// minValue == int.MinValue, maxValue == int.MaxValue
double dbl = num * 1.0 / ((long)uint.MaxValue + 1);
long range = (long)maxValue - minValue;
int result = (int)(dbl * range) + minValue;
return result;
}
完全未经测试......我无法保证结果真的是伪随机的......但创建double
(dbl
)数字的想法与Random
课程。uint.MaxValue
。只有我使用int.MaxValue
作为基础,而不是buffer
。这样我就不必检查ByteArrayOutputStream out = new ByteArrayOutputStream();
YuvImage yuvImage = new YuvImage(data, ImageFormat.NV21, width, height, null);
yuvImage.compressToJpeg(new Rect(0, 0, width, height), 50, out);
byte[] imageBytes = out.toByteArray();
Bitmap image = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length);
iv.setImageBitmap(image);
的负值。
答案 2 :(得分:1)
我提出了一个基于NextBytes的随机整数生成器。 由于使用Int64作为位操作的表示,该方法在正字Int32的字大小范围内平均丢弃了9.62%的位。
字符大小为22位时发生最大位丢失,在字节范围转换中使用64位丢失的64位。在这种情况下,比特效率为68.75%
此外,由于将未绑定范围限制为最大值,因此25%的值会丢失。
小心在返回的IEnumerable上使用Take(N),因为它是一个无限的生成器。
我使用512个长值的缓冲区,因此它一次生成4096个随机字节。如果您只需要几个整数的序列,请将缓冲区大小从512更改为更优的值,直到1。
public static class RandomExtensions
{
public static IEnumerable<int> GetRandomIntegers(this Random r, int max)
{
if (max < 1)
throw new ArgumentOutOfRangeException("max", max, "Must be a positive value.");
const int longWordsTotal = 512;
const int bufferSize = longWordsTotal * 8;
var buffer = new byte[bufferSize];
var wordSize = (int)Math.Log(max, 2) + 1;
while(true)
{
r.NextBytes(buffer);
for (var longWordIndex = 0; longWordIndex < longWordsTotal; longWordIndex++)
{
ulong longWord = BitConverter.ToUInt64(buffer, longWordIndex);
var lastStartBit = 64 - wordSize;
var count = 0;
for (var startBit = 0; startBit <= lastStartBit; startBit += wordSize)
{
count ++;
var mask = ((1UL << wordSize) - 1) << startBit;
var unboundValue = (int)((mask & longWord) >> startBit);
if (unboundValue <= max)
yield return unboundValue;
}
}
}
}
}