【发布时间】:2010-10-15 05:03:30
【问题描述】:
如何在 C# 中使用 Random 类生成随机 Int64 和 UInt64 值?
【问题讨论】:
标签: c# random long-integer int64
如何在 C# 中使用 Random 类生成随机 Int64 和 UInt64 值?
【问题讨论】:
标签: c# random long-integer int64
这应该可以解决问题。 (它是一种扩展方法,因此您可以像在 Random 对象上调用普通的 Next 或 NextDouble 方法一样调用它。
public static Int64 NextInt64(this Random rnd)
{
var buffer = new byte[sizeof(Int64)];
rnd.NextBytes(buffer);
return BitConverter.ToInt64(buffer, 0);
}
如果您想要无符号整数,只需将 Int64 替换为 UInt64 即可,一切正常。
注意:由于没有提供关于生成数字的安全性或所需随机性的上下文(实际上 OP 特别提到了 Random 类),我的示例仅处理 Random类,当随机性(通常量化为information entropy)不是问题时,这是首选解决方案。有趣的是,请参阅提到 RNGCryptoServiceProvider(System.Security 命名空间中提供的 RNG)的其他答案,它们的使用几乎相同。
【讨论】:
使用Random.NextBytes() 和BitConverter.ToInt64 / BitConverter.ToUInt64。
// Assume rng refers to an instance of System.Random
byte[] bytes = new byte[8];
rng.NextBytes(bytes);
long int64 = BitConverter.ToInt64(bytes, 0);
ulong uint64 = BitConverter.ToUInt64(bytes, 0);
请注意,使用 Random.Next() 两次,移动一个值,然后 ORing/adding 不起作用。 Random.Next() 只产生非负整数,即它产生 31 位,而不是 32 位,因此两次调用的结果只产生 62 位随机位,而不是覆盖 Int64/UInt64 的完整范围所需的 64 位。 (Guffa's answer 展示了如何通过 三个 调用 Random.Next() 来做到这一点。)
【讨论】:
Random 值是均匀分布的。我不确定我们是否会通过以下方法获得均匀分布的值,尤其是在我们放弃 MSB 的情况下。我们还可以从 2 个随机数中获取一个值,如果第二次调用是 random.Next(int.MinValue, int.MaxValue),那么所有字节都将被填充。
Random.Next 来完成,即使你想要完整的范围,因为每次调用都会生成 31 位随机数据,而我们总共只需要 64 位。
给你,这使用 crytpo 服务 (不是Random 类),它(理论上)是比 Random 类更好的 RNG。您可以轻松地将其作为 Random 的扩展或创建自己的 Random 类,其中 RNGCryptoServiceProvider 是类级对象。
using System.Security.Cryptography;
public static Int64 NextInt64()
{
var bytes = new byte[sizeof(Int64)];
RNGCryptoServiceProvider Gen = new RNGCryptoServiceProvider();
Gen.GetBytes(bytes);
return BitConverter.ToInt64(bytes , 0);
}
【讨论】:
您可以使用位移将 31 位随机数组合成一个 64 位随机数,但您必须使用三个 31 位数字才能获得足够的位数:
long r = rnd.Next();
r <<= 31;
r |= rnd.Next();
r <<= 31;
r |= rnd.Next();
【讨论】:
我总是使用它来获取我的随机种子(为简洁起见,删除了错误检查):
m_randomURL = "https://www.random.org/cgi-bin/randnum?num=1&min=1&max=1000000000";
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(m_randomURL);
StreamReader stIn = new StreamReader(req.GetResponse().GetResponseStream());
Random rand = new Random(Convert.ToInt32(stIn.ReadToEnd()));
random.org 使用大气噪声来产生随机性,显然用于彩票等。
【讨论】:
你没有说你将如何使用这些随机数...请记住,Random 返回的值不是“加密安全”的,它们不应该用于涉及(大)秘密或(大量)金钱的事情。
【讨论】:
另一个答案是RNGCryptoServiceProvider 而不是Random。在这里您可以看到如何删除 MSB,因此结果始终为正。
public static Int64 NextInt64()
{
var buffer = new byte[8];
new RNGCryptoServiceProvider().GetBytes(buffer);
return BitConverter.ToInt64(buffer, 0) & 0x7FFFFFFFFFFFFFFF;
}
【讨论】:
Random r=new Random();
int j=r.next(1,23);
Console.WriteLine(j);
【讨论】: