2

我附带了以下编码来生成 1000-9999 内的范围:

Dim byt As Byte() = New Byte(1000) {}

Dim rngCrypto As New RNGCryptoServiceProvider()
rngCrypto.GetBytes(byt)

Dim randomNumber As Integer = BitConverter.ToInt32(byt, 9999)
Label4.Text = randomNumber

它显示错误:

指数超出范围。必须是非负数且小于集合的大小。参数名称:startIndex

我已经完成了以下代码。这是正确的吗?

公共子secrand()

    Static r As Random = Nothing

    If r Is Nothing Then
        Dim seed() As Byte = New Byte(4) {}
        Dim rng As New RNGCryptoServiceProvider
        rng.GetBytes(seed)
        r = New Random(BitConverter.ToInt32(seed, 0))
        Label4.Text = r.Next(1000, 9999)
    End If
End Sub
4

1 回答 1

5

第二个参数BitConverter.ToInt32是字节数组的偏移量。对你来说应该是 0。如果您只使用其中的 4 个字节,也没有理由获得 1000 个字节。

C# 中的工作版本:

public static int RandomUniform(int count)
{
    if(count <= 0)
         throw new ArgumentOutOfRangeException("count");
    var rng=new RNGCryptoServiceProvider();
    var bytes=new byte[8];
    rng.GetBytes(bytes, 0);
    return BitConverter.ToUInt64() % (uint)count;
}

Label4.Text = 1000 + RandomUniform(9000);

在 VB.net 中,这看起来类似于

Public Shared Function RandomUniform(count As Integer) As Integer
    If count <= 0 Then
        Throw New ArgumentOutOfRangeException("count")
    End If
    Dim rng = New RNGCryptoServiceProvider()
    Dim bytes = New Byte(8) {}
    rng.GetBytes(bytes, 0)
    Return BitConverter.ToUInt64() Mod CUInt(count)
End Function

这段代码有两个弱点:

  1. 这很慢。的每次调用开销RNGCryptoServiceProvider.GetBytes很大。为了获得更好的性能,请使用几千字节的缓冲区,并且仅GetBytes在用完时调用。
  2. 它不是完全一致的,但对于大多数应用程序来说,偏差应该足够小。

    即使使用count表现出最大偏差的值,您也需要超过 100 亿个样本来检测它,而System.Random少数样本就足够了。即偏差大约比 for 小 80 亿倍System.Random

如果您无法接受其中任何一个弱点,您可以查看我的随机数生成器项目,该项目提供快速、安全和无偏的数字。但这是以添加外部库而不是简单地编写几行代码为代价的。

于 2012-12-03T12:16:38.357 回答