Random number in long range, is this the way?

2019-01-05 01:01发布

Can somebody verify this method. I need a long type number inside a range of two longs. I use the .NET Random.Next(min, max) function which return int's. Is my reasoning correct if I simply divide the long by 2, generate the random number and finally multiply it by 2 again? Or am I too enthusiastic... I understand that my random resolution will decrease but are there any other mistakes which will lead to no such a random number.

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);

标签: c#-4.0 random
13条回答
爷的心禁止访问
2楼-- · 2019-01-05 01:03

Is there anything wrong with using this simple approach?

        long min = 10000000000001;
        long max = 99999999999999;
        Random random = new Random();
        long randomNumber = min + random.Next() % (max - min);

d

查看更多
成全新的幸福
3楼-- · 2019-01-05 01:08

How about generating bytes and converting to int64?

/* generate a byte array, then convert to unint64 */
var r = new Random(); // DONT do this for each call - use a static Random somewhere
var barray = new byte[64/8];
r.NextBytes(barray);
var rint64 = BitConverter.ToUInt64(barray, 0);

Sees to work for me (:

查看更多
ら.Afraid
4楼-- · 2019-01-05 01:10

You're better off taking the difference between minimum and maximum (if it fits in an int), getting a random between 0 and that, and adding it to the minimum.

查看更多
做个烂人
5楼-- · 2019-01-05 01:12

Your randomLong will always be even and you will have eliminated even more values because you are very far away from the maximum for long, The maximum for long is 2^32 * max for int. You should use Random.NextBytes.

查看更多
聊天终结者
6楼-- · 2019-01-05 01:17
private long randomLong()
{
    Random random = new Random();
    byte[] bytes = new byte[8];
    _random.NextBytes(bytes);
    return BitConverter.ToInt64(bytes, 0);
}
查看更多
Summer. ? 凉城
7楼-- · 2019-01-05 01:18

Here is a solution that leverages from the other answers using Random.NextBytes, but also pays careful attention to boundary cases. I've structured it as a set of extension methods. Also, I've accounted for modulo bias, by sampling another random number it falls out of range.

One of my gripes (at least for the situation I was trying to use it) is that the maximum is usually exclusive so if you want to roll a die, you do something like Random.Next(0,7). However, this means you can never get this overload to return the .MaxValue for the datatype (int, long, ulong, what-have-you). Therefore, I've added an inclusiveUpperBound flag to toggle this behavior.

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);
    }
}
查看更多
登录 后发表回答