Share via


Next Random Number

I was expecting (and thus using in places) the Random.Next Method (Int32, Int32) to return a random number between the lower and upper limits specified, both inclusive. However I was surprised to discover that actually "the range of return values includes minValue but not MaxValue. "

As a result, doing something like this (in C#) will never return 5:

        Random rand = new Random();
int num = rand.Next(1, 5);

Maybe this is obvious to some, but to me it wasn't and I was intuitively expecting both limits to be inclusive.

The logic behind having this behavior, I would guess, is the presumed familiarity of the C# developer with zero-based access. Since I found it confusing could it instead be a usability issue (we needed to run it by more developers to decide the correct behavior)?

Maybe MSDN documentation needs to start using bold red for words like "not" in such docs.

Comments

  • Anonymous
    October 21, 2004
    [0, n) is the expected and most useful behaviour for those with a mathematical background.

  • Anonymous
    October 21, 2004
    The comment has been removed

  • Anonymous
    October 21, 2004
    It's because that function is multiplying a random Double value in the range [0,1] (as far as I can tell) by the difference between maxValue and minValue, casting the result as an int, and finally adding minValue to this product.

    To end up with maxValue as the returned result, the sampled Double mentioned above would have to be exactly 1, because the cast to Integer doesn't round to the closest int, it always rounds down. The probability of this occuring is therefore very small.

    I'm sure someone will correct me if I'm missing something important...

    The disassembly from Reflector looks like this:

    Public Overridable Function [Next](ByVal minValue As Integer, ByVal maxValue As Integer) As Integer
    If (minValue > maxValue) Then
    Throw New ArgumentOutOfRangeException("minValue", String.Format(Environment.GetResourceString("Argument_MinMaxValue"), "minValue", "maxValue"))
    End If
    Dim num1 As Integer = (maxValue - minValue)
    If (num1 < 0) Then
    Dim num2 As Long = (maxValue - minValue)
    Return CType((CType((Me.Sample * num2),Long) + minValue),Integer)
    End If
    Return (CType((Me.Sample * num1),Integer) + minValue)
    End Function


  • Anonymous
    October 21, 2004
    its called a half-open interval, and it has all kinds of usefull properties:

    http://encyclopedia.thefreedictionary.com/Half-open%20interval

  • Anonymous
    October 21, 2004
    The comment has been removed

  • Anonymous
    October 21, 2004
    I got caught by this too. I agree with Luc, and suggest that maxValue be changed to LessThan - that's pretty obvious then!

  • Anonymous
    October 22, 2004
    Great feedback!

    Seems like the Math background theory is probably the reason, but since not many "typical" developers would have a Math background, it seems worth considering for a revision. I did know about half-open (or half-closed) intervals and closed intervals but still expected it to be a closed rather than a half-open interval - based probably on the semantics of the parameter "MaxValue".

    I like Luc's suggestion the best - a very simple and elegant solution, and I like it all the more because Intellisense (in VS) has gotten so good that many developers would learn about an API more through the explanation that shows up there rather than through the docs and help. This would solve the problem at the closest-to-the-developer level and is also probably the cheapest solution.

    BTW - the link I have in the post is to the single parameter version of Random.Next method, instead of the 2 parameter one below.

    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemrandomclassnexttopic3.asp

  • Anonymous
    March 01, 2007
    The comment has been removed

  • Anonymous
    May 03, 2007
    I propose the method description is renamed thus: Random.Next(int minValue, int maxValueWhichCannotBeReturnedAsAResultOfNextButCannotBeExceeded) or perhaps: Random.Next(int minValue, int beyondMaxValue) would be easier?

  • Anonymous
    May 28, 2008
    The comment has been removed