【问题标题】:C# Get only numbers 1-15 from RNGCryptoServiceProvider?C# 仅从 RNGCryptoServiceProvider 获取数字 1-15?
【发布时间】:2013-05-09 12:03:08
【问题描述】:

由于 RNGCryptoServiceProvider 比 Random() 更“安全”(产生高质量的随机数),我觉得使用它。性能不是问题。但是,不是读取最后一个数字,而是以某种方式决定何时在其前面添加 0 或 1。有没有更好(更准确)的方法?

byte[] data = new byte[4];
rng.GetBytes(data);
int value = BitConverter.ToInt32(data, 0);
Console.WriteLine(value);

【问题讨论】:

  • “更安全”?这意味着什么? APC 比我的车更安全,但我认为与我的车一起工作不值得。
  • 产生更好的随机数
  • “更好”在什么意义上?
  • “更好”也不是一个科学术语。它产生加密安全随机数。如果您不将它们用于无关紧要的加密货币。此外,通过自己修改数字,您实际上是在破坏它们的加密强度属性。那么你得到了什么?
  • @Jon System.Random 即使对于非加密数字也不理想。它很难播种,在某些情况下它有很大的偏差,......

标签: c# random


【解决方案1】:

您可以使用modulo operator (%)。这会导致结果略有偏差,但对于 8 字节输入,偏差非常小。比System.Random 的偏差小得多。

byte[] data = new byte[8];
rng.GetBytes(data);
ulong value = BitConverter.ToUInt64(data, 0);
result = (int)(value%15+1);

或者如果你想要完全统一的数字:

byte[] data = new byte[8];
ulong value;
do
{
    rng.GetBytes(data);
    value = BitConverter.ToUInt64(data, 0);
} while(value==0);
result = (int)(value%15+1);

【讨论】:

  • 需要明确的是,通过观察 2^64 % 15 是 1 可以得到一个完全无偏的均匀分布,因此如果你得到准确的 0 则丢弃并重新滚动您最终会得到 15 个值的精确倍数,您可以向左滚动 - 完全可整除。
  • 啊,太好了!我猜它仍然会产生比使用 ​​Random() 更好质量的随机数
  • @Patashu 如果结果正好是 0,那么抛出/忽略结果?
  • @Half_Baked 拒绝号码再试一次。
  • @CodesInChaos 谢谢老兄!非常感谢您花时间编写代码示例!
【解决方案2】:

很简单:

static int getnum15(RNGCryptoServiceProvider RngCsp)
{
    byte[] p=new byte[1];
    do {
        RngCsp.GetBytes(p);
    } while (p[0]==255);
    return(p[0]%15);
}

因为 256 mod 15=1。 那么

RNGCryptoServiceProvider rngCsp=new RNGCryptoServiceProvider();
for (int i=0;i<30;i++)
    Console.WriteLine(getnum15(rngCsp));

【讨论】:

    【解决方案3】:

    没有办法让 RNGCryptoServiceProvider 给你数字,因为它不适合算术。在密码学中,您使用单词和字节。如果需要不同的 RNG 用于算术目的,请选择 different library

    【讨论】:

    • 即使在密码学中,有时您也需要从 0 到 n-1 的数字。例如,在创建随机字母数字标记时。就我个人而言,我总是使用加密级 PRNG,即使是数字工作。
    猜你喜欢
    • 2016-06-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多