远程随机数,是这样的吗?

Nic*_*k V 45 random c#-4.0

有人可以验证这种方法.我需要在两个长度范围内的长型号码.我使用返回int的.NET Random.Next(min,max)函数.如果我将long除以2,生成随机数并最终再乘以2,我的推理是否正确?或者我太热情......我明白我的随机解决方案会减少但是还有其他错误导致没有这样的随机数.

long min = st.MinimumTime.Ticks;    //long is Signed 64-bit integer
long max = st.MaximumTime.Ticks;
int minInt = (int) (min / 2);      //int is Signed 64-bit integer
int maxInt = (int) (max / 2);      //int is Signed 64-bit integer

Random random = new Random();
int randomInt = random.Next(minInt, maxInt);
long randomLong = (randomInt * 2);
Run Code Online (Sandbox Code Playgroud)

Dyp*_*ppl 82

为什么不直接生成两个随机Int32值并从中生成一个Int64

long LongRandom(long min, long max, Random rand) {
    long result = rand.Next((Int32)(min >> 32), (Int32)(max >> 32));
    result = (result << 32);
    result = result | (long)rand.Next((Int32)min, (Int32)max);
    return result;
}
Run Code Online (Sandbox Code Playgroud)

对不起,我忘了第一次添加边界.添加minmax参数.你可以这样测试:

long r = LongRandom(100000000000000000, 100000000000000050, new Random());
Run Code Online (Sandbox Code Playgroud)

的值r将处于期望的范围内.

编辑:上面的实现是有缺陷的.为了避免有符号无符号问题,生成4个16位整数而不是2个32位整数可能是值得的.但是在这一点上解决方案失去了它的优雅,所以我认为最好坚持使用Random.NextBytes版本:

long LongRandom(long min, long max, Random rand) {
    byte[] buf = new byte[8];
    rand.NextBytes(buf);
    long longRand = BitConverter.ToInt64(buf, 0);

    return (Math.Abs(longRand % (max - min)) + min);
}
Run Code Online (Sandbox Code Playgroud)

在价值分布方面看起来相当不错(通过我运行的非常简单的测试来判断).

  • 不能正常工作.`LongRandom(long.MinValue,long.MaxValue,new Random())`,总是返回`-9223372036854775808`.在任何情况下,`Math.Abs​​()`会破坏一位,留下63个随机位.如果您只有63个随机位,则不能提供64位随机数. (11认同)
  • @ user839032:它实际上有bug,上面的代码段是为了演示和想法.我将在稍后通过强大的解决方案更新答案 (2认同)

Blu*_*eft 28

这里的一些其他答案有两个问题:具有模偏差,并且无法正确处理其值max = long.MaxValue.(马丁的答案既没有问题,但他的代码在大范围内是不合理的慢.)

以下代码将解决所有这些问题:

//Working with ulong so that modulo works correctly with values > long.MaxValue
ulong uRange = (ulong)(max - min);

//Prevent a modolo bias; see https://stackoverflow.com/a/10984975/238419
//for more information.
//In the worst case, the expected number of calls is 2 (though usually it's
//much closer to 1) so this loop doesn't really hurt performance at all.
ulong ulongRand;
do
{
    byte[] buf = new byte[8];
    random.NextBytes(buf);
    ulongRand = (ulong)BitConverter.ToInt64(buf, 0);
} while (ulongRand > ulong.MaxValue - ((ulong.MaxValue % uRange) + 1) % uRange);

return (long)(ulongRand % uRange) + min;
Run Code Online (Sandbox Code Playgroud)

以下完整记录的类可以放入您的代码库中,以轻松实现上述解决方案并且无需大脑.与Stackoverflow上的所有代码一样,它在CC归属下获得许可,因此您可以随意使用它,无论您想要什么.

using System;

namespace MyNamespace
{
    public static class RandomExtensionMethods
    {
        /// <summary>
        /// Returns a random long from min (inclusive) to max (exclusive)
        /// </summary>
        /// <param name="random">The given random instance</param>
        /// <param name="min">The inclusive minimum bound</param>
        /// <param name="max">The exclusive maximum bound.  Must be greater than min</param>
        public static long NextLong(this Random random, long min, long max)
        {
            if (max <= min)
                throw new ArgumentOutOfRangeException("max", "max must be > min!");

            //Working with ulong so that modulo works correctly with values > long.MaxValue
            ulong uRange = (ulong)(max - min);

            //Prevent a modolo bias; see https://stackoverflow.com/a/10984975/238419
            //for more information.
            //In the worst case, the expected number of calls is 2 (though usually it's
            //much closer to 1) so this loop doesn't really hurt performance at all.
            ulong ulongRand;
            do
            {
                byte[] buf = new byte[8];
                random.NextBytes(buf);
                ulongRand = (ulong)BitConverter.ToInt64(buf, 0);
            } while (ulongRand > ulong.MaxValue - ((ulong.MaxValue % uRange) + 1) % uRange);

            return (long)(ulongRand % uRange) + min;
        }

        /// <summary>
        /// Returns a random long from 0 (inclusive) to max (exclusive)
        /// </summary>
        /// <param name="random">The given random instance</param>
        /// <param name="max">The exclusive maximum bound.  Must be greater than 0</param>
        public static long NextLong(this Random random, long max)
        {
            return random.NextLong(0, max);
        }

        /// <summary>
        /// Returns a random long over all possible values of long (except long.MaxValue, similar to
        /// random.Next())
        /// </summary>
        /// <param name="random">The given random instance</param>
        public static long NextLong(this Random random)
        {
            return random.NextLong(long.MinValue, long.MaxValue);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

用法:

Random random = new Random();
long foobar = random.NextLong(0, 1234567890L);
Run Code Online (Sandbox Code Playgroud)

  • 我的时间表明我的代码需要大约210ms才能在`long.MinValue`和`long.MaxValue`之间生成1,000,000个随机数,并且在相同的范围和迭代次数上需要大约260ms.非常快,我只是在辩护我的代码不是"在大范围内不合理地慢" (2认同)

age*_*t-j 26

这通过使用随机字节创建随机Int64,如果数字超出安全范围,则通过重试避免模偏.

static class RandomExtensions
{
   public static long RandomLong(this Random rnd)
   {
      byte[] buffer = new byte[8];
      rnd.NextBytes (buffer);
      return BitConverter.ToInt64(buffer, 0);
   }

   public static long RandomLong(this Random rnd, long min, long max)
   {
      EnsureMinLEQMax(ref min, ref max);
      long numbersInRange = unchecked(max - min + 1);
      if (numbersInRange < 0)
         throw new ArgumentException("Size of range between min and max must be less than or equal to Int64.MaxValue");

      long randomOffset = RandomLong(rnd);
      if (IsModuloBiased(randomOffset, numbersInRange))
         return RandomLong(rnd, min, max); // Try again
      else
         return min + PositiveModuloOrZero(randomOffset, numbersInRange);
   }

   static bool IsModuloBiased(long randomOffset, long numbersInRange)
   {
      long greatestCompleteRange = numbersInRange * (long.MaxValue / numbersInRange);
      return randomOffset > greatestCompleteRange;
   }

   static long PositiveModuloOrZero(long dividend, long divisor)
   {
      long mod;
      Math.DivRem(dividend, divisor, out mod);
      if(mod < 0)
         mod += divisor;
      return mod;
   }

   static void EnsureMinLEQMax(ref long min, ref long max)
   {
      if(min <= max)
         return;
      long temp = min;
      min = max;
      max = temp;
   }
}
Run Code Online (Sandbox Code Playgroud)

  • 你应该真的命名你的扩展方法`NextLong`而不是`RandomLong`,因为它们将遵循`Random`类的现有方法的命名约定. (6认同)

Mar*_*eal 7

这是一个利用其他答案的解决方案Random.NextBytes,但也要注意边界情况.我把它构建为一组扩展方法.此外,我已经考虑了模偏差,通过采样另一个落在范围之外的随机数.

我的一个抱怨(至少对于我试图使用它的情况)是最大值通常是独占的,所以如果你想掷骰子,你会做类似的事情Random.Next(0,7).但是,这意味着你永远无法得到这个过载返回.MaxValue的数据类型(int,long,ulong,什么具备的,你).因此,我添加了一个inclusiveUpperBound标志来切换此行为.

public static class Extensions
{
    //returns a uniformly random ulong between ulong.Min inclusive and ulong.Max inclusive
    public static ulong NextULong(this Random rng)
    {
        byte[] buf = new byte[8];
        rng.NextBytes(buf);
        return BitConverter.ToUInt64(buf, 0);
    }

    //returns a uniformly random ulong between ulong.Min and Max without modulo bias
    public static ulong NextULong(this Random rng, ulong max, bool inclusiveUpperBound = false)
    {
        return rng.NextULong(ulong.MinValue, max, inclusiveUpperBound);
    }

    //returns a uniformly random ulong between Min and Max without modulo bias
    public static ulong NextULong(this Random rng, ulong min, ulong max, bool inclusiveUpperBound = false)
    {
        ulong range = max - min;

        if (inclusiveUpperBound)
        {   
            if (range == ulong.MaxValue)
            {
                return rng.NextULong();
            }

            range++;
        }

        if (range <= 0)
        {
            throw new ArgumentOutOfRangeException("Max must be greater than min when inclusiveUpperBound is false, and greater than or equal to when true", "max");
        }

        ulong limit = ulong.MaxValue - ulong.MaxValue % range;
        ulong r;
        do
        {
            r = rng.NextULong();
        } while(r > limit);

        return r % range + min;
    }

    //returns a uniformly random long between long.Min inclusive and long.Max inclusive
    public static long NextLong(this Random rng)
    {
        byte[] buf = new byte[8];
        rng.NextBytes(buf);
        return BitConverter.ToInt64(buf, 0);
    }

    //returns a uniformly random long between long.Min and Max without modulo bias
    public static long NextLong(this Random rng, long max, bool inclusiveUpperBound = false)
    {
        return rng.NextLong(long.MinValue, max, inclusiveUpperBound);
    }

    //returns a uniformly random long between Min and Max without modulo bias
    public static long NextLong(this Random rng, long min, long max, bool inclusiveUpperBound = false)
    {
        ulong range = (ulong)(max - min);

        if (inclusiveUpperBound)
        {   
            if (range == ulong.MaxValue)
            {
                return rng.NextLong();
            }

            range++;
        }

        if (range <= 0)
        {
            throw new ArgumentOutOfRangeException("Max must be greater than min when inclusiveUpperBound is false, and greater than or equal to when true", "max");
        }

        ulong limit = ulong.MaxValue - ulong.MaxValue % range;
        ulong r;
        do
        {
            r = rng.NextULong();
        } while(r > limit);
        return (long)(r % range + (ulong)min);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这有效!即使在极端情况下也是 (long.MinValue, long.MaxValue)。 (2认同)

小智 5

private long randomLong()
{
    Random random = new Random();
    byte[] bytes = new byte[8];
    random.NextBytes(bytes);
    return BitConverter.ToInt64(bytes, 0);
}
Run Code Online (Sandbox Code Playgroud)