简体   繁体   中英

How to get 4 unique random numbers in range <0;9>?

I want to get 4 unique random floating point numbers in the range <0;9>. How could I do that. Is it possible to do this with a single function so I don't need to generate random numbers in a loop?

var rng = new Random();
int first = rng.Next(10);
int second = rng.Next(10);
int third = rng.Next(10);
int fourth = rng.Next(10);

If you need four distinct values then you can do something like this...

var rng = new Random();
var values = Enumerable.Range(0, 10).OrderBy(x => rng.Next()).ToArray();
int first = values[0];
int second = values[1];
int third = values[2];
int fourth = values[3];

Note that if you needed to generate many numbers then a proper shuffle implementation will give better performance than OrderBy : O(n) rather than O(n log n). If you only need a handful of numbers then OrderBy will be fine.

I am sorry but I could not resist

http://xkcd.com/221/

In that spirit you can do

r1=2.7;
r2=6.9;
r3=4.2;
r4=8.1;

I swear they are random

This is what I use to get distinct random numbers in a given range:

var random = new Random();

int take = 4;
int rangeMin = 0;
int rangeMax = 10;

var randomUniqueNumbers = Enumerable.Range(0, int.MaxValue)
    .Select(i => random.Next(rangeMin, rangeMax))
    .Distinct()
    .Take(Math.Min(take, rangeMax - rangeMin));

It would be nicer with an Infinite enumeration insted of Enumerable.Range(0, int.MaxValue), but this does the job.

so I don't need to generate random numbers in a loop?

Since your range is so limited, you can generate a number in [0, 9999] and use decimal digit extraction. This will likely improve performance, but only very slightly. Personally, I would just use a loop.

int fourDigit = m_Random.Next(10000);
int first = fourDigit % 10; fourDigit /= 10;
int second = fourDigit % 10; fourDigit /= 10;
int third = fourDigit % 10; fourDigit /= 10;
int fourth = fourDigit;

The original poster has clarified that the numbers are to be distinct. This practically necessitates a loop at least somewhere in the code. However, I do not think it requires multiple calls to Random , by adapting the above.

NOTE : I am not sure if this incrementing technique is free of bias, if someone familiar with the mathematics behind random numbers would be so kind to analyze. Thanks.

int fourDigit = m_Random.Next(10000);
int first = fourDigit % 10; fourDigit /= 10;
int second = fourDigit % 10; while (second == first) second = (second + 1) % 10; fourDigit /= 10;
int third = fourDigit % 10; while (third == first || third == second) third = (third + 1) % 10; fourDigit /= 10;
int fourth = fourDigit; while (fourth == first || fourth == second || fourth == third) fourth = (fourth + 1) % 10;

Why not do:

    Enumerable.Range(0, 9)
              .OrderBy(x => Guid.NewGuid().GetHashCode())
              .Take(4)
              .ToArray();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM