int.MinValue和int.MaxValue之间的随机数(含)

时间:2019-07-19 19:08:16

标签: c# .net random

这有点令人困惑:data_set = [[1,25],[1,30],[1,35],[1,40],[1,45] ,[2,35],[2,40],[2,44],[2,50],[2,55],[2,58] ,[3,49],[3,54],[3,60],[3,64],[3,68] ,[4,50],[4,63],[4,65],[4,73],[4,78],[4,83],[4,85] ,[5,72],[5,77],[5,80],[5,86],[5,88],[5,95]] # Convert data_set to dictionary data_set_dict = {} for x, y in data_set: if x not in data_set_dict: data_set_dict[x] = [] data_set_dict[x].append(y) # Calculate mean y for each x in dictionary for x, ys in data_set_dict.items(): print(f'X: {x}, Mean Y: {sum(ys)/len(ys)}') 具有一个接受最小值和最大值的重载。此重载返回一个大于或等于最小值(包含)且小于最大值(不含)的数字。

我想包括整个范围,包括最大值。在某些情况下,我可以通过将最大值加一个来完成此操作。但是在这种情况下,最大值可以为Random.Next(),并且向其中添加一个值将无法完成我想要的操作。

那么,有没有人知道从int.MaxValueint.MinValue(包括两端)之间随机数的好窍门?

更新:

请注意,下限范围可以是int.MaxValue,但也可以是其他范围。如果我知道它永远是int.MinValue,那么问题会更简单。

13 个答案:

答案 0 :(得分:7)

不强制转换,不#include <bits/stdc++.h> using namespace std; int main() { int t; cin >> t; while (t--) { int n; cin >> n; int arr[n]; for (int i = 0; i < n; i++) { cin >> arr[i]; } int k; cin >> k; int flag[n] = {0}; int p = 0; int q = 0; if (n % 2 != 0) { cout << "False" << endl; } else { for (int i = 0; i < n; i++) { for (int j = i + 1; j < n; j++) { if ((arr[i] + arr[j]) % k == 0 && flag[j] == 0) { p = 1; flag[j] = 1; } } if (p == 0) { q = 1; cout << "False" << endl; break; } } if (q == 0) { cout << "True" << endl; } } } return 0; } ,考虑到所有边界情况,最佳性能。

long

答案 1 :(得分:4)

嗯,我有个窍门。我不确定我会把它描述为“好把戏”,但我觉得它可能有用。

public static class RandomExtensions
{
    public static int NextInclusive(this Random rng, int minValue, int maxValue)
    {
        if (maxValue == int.MaxValue)
        {
            var bytes = new byte[4];
            rng.NextBytes(bytes);
            return BitConverter.ToInt32(bytes, 0);
        }
        return rng.Next(minValue, maxValue + 1);
    }
}

因此,基本上是一种扩展方法,如果上限为int.MaxValue并将仅转换为int,则将仅生成四个字节,否则将使用标准的Next(int, int)重载。

请注意,如果maxValueint.MaxValue,它将忽略minValue。猜猜我没有考虑到这一点...

答案 2 :(得分:3)

保证可以使用负值和非负值:

public static int NextIntegerInclusive(this Random r, int min_value, int max_value)
{
  if (max_value < min_value)
  {
    throw new InvalidOperationException("max_value must be greater than min_value.");
  }
  long offsetFromZero =(long)min_value; // e.g. -2,147,483,648
  long bound = (long)max_value; // e.g. 2,147,483,647
  bound -= offsetFromZero; // e.g. 4,294,967,295 (uint.MaxValue)
  bound += Math.Sign(bound); // e.g. 4,294,967,296 (uint.MaxValue + 1)
  return (int) (Math.Round(r.NextDouble() * bound) + offsetFromZero); // e.g. -2,147,483,648 => 2,147,483,647
}

答案 3 :(得分:1)

将范围一分为二,并补偿MaxValue

r.Next(2) == 0 ? r.Next(int.MinValue, 0) : (1 + r.Next(-1, int.MaxValue))

如果我们使范围相等,则通过不同的数学运算可以获得相同的结果。这里我们依靠int.MinValue = -1 - int.MaxValue

r.Next(int.MinValue, 0) - (r.Next(2) == 0 ? 0 : int.MinValue)

答案 4 :(得分:1)

据我了解,您希望Random给出一个介于-2.147.483.648和+2.147.483.647之间的值。但是问题在于,由于这些值只能给出-2.147.483.648到+2.147.483.64 6 之间的值,因此是随机的,因为最大值是唯一的。

选项0:拿走东西,学会不用它

道格拉斯·亚当斯(Douglas Adams)并不是程序员AFAIK,但他为我们提供了一些好的建议:“使任何事物变得不可见的技术是如此复杂,以至于999,900,99,900,9在一万亿分之一中,有十九万九千九百九十九次,只是把东西拿走而不做就更简单和有效了。”

可能是这种情况。

选项1:我们需要更大的随机数!

Random.Next使用Int32作为参数。我可以考虑的一种选择是使用其他随机函数,可以将下一个更高级别的整数(Int64)作为输入。 Int32隐式转换为Int64。 Int64 Number = Int64(Int32.MaxValue)+1;

但是afaik,您必须在.NET库之外进行此操作。届时,您最好寻找一个包含最大值的随机数。

但是我认为必须从一个数值中排除一个数学原因。

选项2:更多滚动

另一种方法是使用两次Random调用-每次调用范围的一半-然后将它们相加。

Number1 = rng.Next(-2.147.483.648, 0);
Number2 = rng.Next(0, 2.147.483.647);
resut = Number1 + Number2;

但是我有90%的把握会破坏randon的分布。我在P&P RPG方面的经验给了我一些骰子机会的经验,而且我知道滚动2个骰子(或相同的2次)的事实会给您带来与一个特定骰子非常不同的结果分配。如果不需要这种随机分布,则可以选择。但是,如果您不太在意他的分布,那值得一试。

选项3:您需要全部产品吗?还是只关心最小值和最大值?

我假设您正在进行某种形式的测试,并且您需要Int.MaxValue和Int.MinValue都在范围内。但是,您是否还需要介于之间的每个值,或者如果没有其中一个,就可以吗? 如果您必须舍弃某个值,您会更愿意先减少4而不是Int.MaxValue吗?

Number = rng.Next(Int.MinValue, Int.MaxValue);
if(Number > 3)
  Number = Number +1;
这样的

代码将为您提供MinValue和Maxvalue之间的每个数字,除4 外。但是在大多数情况下,可以处理3和5的代码也可以处理4。不需要显式测试4。

当然,假设4不是必须运行的重要测试编号(出于这些原因,我避免使用1和0)。您还可以决定随机“跳过”该数字:

skipAbleNumber = rng.Next(Int.MinValue +1, Int.MaxValue);

然后使用> skipAbleNumber而不是> 4

答案 5 :(得分:1)

这实际上不是Random.Next(int,int)的实现,这是很有趣的,因为您可以从包含性的行为中派生出“排他性”的行为,而反之则不能。

public static class RandomExtensions
{
    private const long IntegerRange = (long)int.MaxValue - int.MinValue;

    public static int NextInclusive(this Random random, int minValue, int maxValue)
    {
        if (minValue > maxValue)
        {
            throw new ArgumentOutOfRangeException(nameof(minValue));
        }

        var buffer = new byte[4];
        random.NextBytes(buffer);
        var a = BitConverter.ToInt32(buffer, 0);
        var b = a - (long)int.MinValue;
        var c = b * (1.0 / IntegerRange);
        var d = c * ((long)maxValue - minValue + 1);
        var e = (long)d + minValue;
        return (int)e;
    }
}
new Random(0).NextInclusive(int.MaxValue - 1, int.MaxValue); // returns int.MaxValue
new Random(1).NextInclusive(int.MaxValue - 1, int.MaxValue); // returns int.MaxValue - 1
new Random(0).NextInclusive(int.MinValue, int.MinValue + 1); // returns int.MinValue + 1
new Random(1).NextInclusive(int.MinValue, int.MinValue + 1); // returns int.MinValue
new Random(-451732719).NextInclusive(int.MinValue, int.MaxValue); // returns int.MinValue
new Random(-394328071).NextInclusive(int.MinValue, int.MaxValue); // returns int.MaxValue

答案 6 :(得分:1)

您不能使用Random.Next()来实现所需的功能,因为您不能将N的数字序列与N+1对应,并且不能遗漏一个:)。期间。

但是您可以使用Random.NextDouble(),它返回双重结果: 0 <= x < 1又称[0, 1) 在0(其中[是包含符号和)排斥)之间

我们如何将N个数字对应于[0,1)? 您需要将[0, 1)分成N个相等的段: [0, 1/N)[1/N, 2/N),... [N-1/N, 1)

在这里重要的是,一个边界是包容性的,而另一个边界是排斥性的-所有N个段都是绝对相等的!

这是我的代码:我将其作为一个简单的控制台程序进行了构建。

class Program
    {
        private static Int64 _segmentsQty;
        private static double _step;
        private static Random _random = new Random();

        static void Main()
        {
            InclusiveRandomPrep();
            for (int i = 1; i < 20; i++)
            {
                Console.WriteLine(InclusiveRandom());
            }

            Console.ReadLine();
        }

        public static void InclusiveRandomPrep()
        {
            _segmentsQty = (Int64)int.MaxValue - int.MinValue;
            _step = 1.0 / _segmentsQty;
        }
        public static int InclusiveRandom()
        {
            var randomDouble = _random.NextDouble();
            var times = randomDouble / _step;
            var result = (Int64)Math.Floor(times);
            return (int)result + int.MinValue;
        }
    }

答案 7 :(得分:1)

您可以将1随机添加到生成的数字,使其仍然是随机的,并覆盖整个范围的整数。

public static class RandomExtension
{
    public static int NextInclusive(this Random random, int minValue, int maxValue)
    {
        var randInt = random.Next(minValue, maxValue);
        var plus = random.Next(0, 2);

        return randInt + plus;
    }
}

答案 8 :(得分:0)

您可以使用此技巧:

Random.Next(int.MinValue, 1) + (Random.Next(-1, int.MaxValue) + 1);

或者如果要使其均匀分布:

int a;
a = Random.Next(2);
Random.Next(int.MinValue, 0) * a + (Random.Next(-1, int.MaxValue) + 1) * (1 - a);

答案 9 :(得分:0)

那呢?

   using System;

    public class Example
    {
       public static void Main()
       {
          Random rnd = new Random();
          int min_value = max_value;
          int max_value = min_value;

          Console.WriteLine("\n20 random integers from 10 to 20:");
          for (int ctr = 1; ctr <= 20; ctr++) 
          {
             Console.Write("{0,6}", rnd.Next(min_value, max_value));
             if (ctr % 5 == 0) Console.WriteLine();
          }
       }
    }

答案 10 :(得分:0)

您可以尝试一下。有点骇人听闻,但可以同时为您提供最大和最小的包容性。

static void Main(string[] args)
        {
            int x = 0;

            var r = new Random();

            for (var i = 0; i < 32; i++)
            {
                x = x | (r.Next(0, 2) << i);

            }

            Console.WriteLine(x);
            Console.ReadKey();
        }

答案 11 :(得分:0)

这对您有用吗?

int random(Random rnd, int min, int max) 
{
    return Convert.ToInt32(rnd.NextDouble() * (max - min) + min);
}

答案 12 :(得分:0)

Random.Next(int minValue, int maxValue)的{​​{3}}会生成两个大范围样本,例如Int32.MinValueInt32.MaxValue之间的样本。对于NextInclusive方法,我不得不使用另一个较大范围的Next,总共有四个样本。因此,性能应与填充4个字节(每个字节一个样本)的缓冲区的版本相当。

public static class RandomExtensions
{
    public static int NextInclusive(this Random random, int minValue, int maxValue)
    {
        if (maxValue == Int32.MaxValue)
        {
            if (minValue == Int32.MinValue)
            {
                var value1 = random.Next(Int32.MinValue, Int32.MaxValue);
                var value2 = random.Next(Int32.MinValue, Int32.MaxValue);
                return value1 < value2 ? value1 : value1 + 1;
            }
            return random.Next(minValue - 1, Int32.MaxValue) + 1;
        }
        return random.Next(minValue, maxValue + 1);
    }

}

一些结果:

new Random(0).NextInclusive(int.MaxValue - 1, int.MaxValue); // returns int.MaxValue
new Random(1).NextInclusive(int.MaxValue - 1, int.MaxValue); // returns int.MaxValue - 1
new Random(0).NextInclusive(int.MinValue, int.MinValue + 1); // returns int.MinValue + 1
new Random(1).NextInclusive(int.MinValue, int.MinValue + 1); // returns int.MinValue
new Random(24917099).NextInclusive(int.MinValue, int.MaxValue); // returns int.MinValue
var random = new Random(784288084);
random.NextInclusive(int.MinValue, int.MaxValue);
random.NextInclusive(int.MinValue, int.MaxValue); // returns int.MaxValue