dice rolling problem

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Jose Durazo

    dice rolling problem

    Hello, I'm doing an exercise to simulate rolling a pair of dice 36,000
    times, then count and display how many times the simulation rolls each
    possible sum.

    For some reason each time I run my simulation, one or more of my sums is
    zero, which is highly unlikely. So I'm sure there's a bug in my code. But
    I can't tell what it is, even after re-reading it several times. Can
    someone give me a hint?

    Here is my code:

    static void SimulateDiceRol ls()
    {
    // When you roll two dice, there are 11 possible sums:
    // 2, 3, ..., 10, 11, 12. Define an array of 13 elements
    // where the first two elements are unused, but the third element
    // where index equals 2, corresponds to sum = 2, and so on.
    // make sure they're initialized to 0, which C# does by default
    int[] sum = new int[13];

    // for 36,000 times, roll two dice, calculate the sum,
    // and increment the index corresponding to that sum.
    int currentResult = 0;
    for (int numberOfRolls = 1; numberOfRolls <= 36000; ++numberOfRolls )
    {
    currentResult = RollTwoDice();
    ++sum[currentResult];
    }

    // print how many times each sum comes up and what percent of the time
    // to a 3 decimal precision that sum comes up
    for (int sumIndex = 2; sumIndex <= 12; ++sumIndex)
    {
    Console.WriteLi ne("{0,5} {1,5} {2:F3}", sumIndex, sum[sumIndex],
    (double)sum[sumIndex] / 36000 * 100);
    }
    }

    // return the sum of two randomly generated integers from 1 to 6
    // inclusive
    static int RollTwoDice()
    {
    Random r = new Random();
    return r.Next(1, 7) + r.Next(1, 7);
    }

    Thanks in advance,
    Jose


  • Jose Durazo

    #2
    Re: dice rolling problem

    I changed my code to the folllowing which fixes the problem.
    But I don't care about getting the program to work as much as I would like
    to know what I did wrong in my first example. Can anyone help explain what
    I did wrong in the code from my earlier post?

    Thanks!

    Working code:

    static void SimulateDiceRol ls()
    {
    // When you roll two dice, there are 11 possible sums:
    // 2, 3, ..., 10, 11, 12. Define an array of 13 elements
    // where the first two elements are unused, but the third element
    // where index equals 2, corresponds to sum = 2, and so on.
    // make sure they're initialized to 0, which C# does by default
    int[] sum = new int[13];
    Random r = new Random();

    // for 36,000 times, roll two dice, calculate the sum,
    // and increment the index corresponding to that sum.
    int currentResult = 0;
    for (int numberOfRolls = 1; numberOfRolls <= 36000; ++numberOfRolls )
    {
    currentResult += r.Next(1, 7);
    currentResult += r.Next(1, 7);
    ++sum[currentResult];
    currentResult = 0;
    }

    // print how many times each sum comes up and what percent of the time
    // to a 2 decimal precision that sum comes up
    for (int sumIndex = 2; sumIndex <= 12; ++sumIndex)
    {
    Console.WriteLi ne("{0,5} {1,5} {2:F3}", sumIndex, sum[sumIndex],
    (double)sum[sumIndex] / 36000 * 100);
    }
    }


    Comment

    • Marc Gravell

      #3
      Re: dice rolling problem

      I believe the problem is your usage of Random; for tight-loops you need
      to use a single instance, otherwise successive objects in a similar
      time interval (tiny amounts of time apart) will have the same seed.

      This shoud fix it:

      static readonly Random _rand = new Random();
      static int RollTwoDice()
      {
      return _rand.Next(1,7) + _rand.Next(1,7) ;
      }

      Marc

      Comment

      • Jose Durazo

        #4
        Re: dice rolling problem

        I see. So my super short loop would call RollTwoDice(), increment a
        counter, and then, say, before the next millisecond, it would call
        RollTwoDice(), perhaps many times before a new seed would be used. So
        given that usually two or three out of 11 dice sums never got rolled in
        36,000 tries, I'd guess one number got rolled several thousand times in a
        row, then another number several thousand times after that, and so on.

        I'll make a version of my original program that will tell me if this is the
        case.

        Thanks for pointing me in what really looks like the right direction!

        -Jose


        Comment

        • Jose Durazo

          #5
          Re: dice rolling problem

          I put a Console.Write() statement in my loop which tells me which number was
          generated i each iteration. This makes each iteration take a lot longer,
          but still each "random" number was generated dozens of times in a row. So
          you were right!

          Once again, thanks Marc.

          -Jose


          Comment

          • Marc Gravell

            #6
            Re: dice rolling problem

            An oft-found trap ;-p

            Just for completeness, Jon Skeet has a StaticRandom class in one of
            his tool-bags which may be of interest to anyone using occasional
            random numbers (useful where this type of private Random instance is
            inconvenient due to e.g. threading / scoping constraints). Assuming
            your code is not threaded, then for this type of tight loop I would
            recommend the solution already posted (a "local" fixed instance),
            purely to avoid the overhead of locking etc associated with static
            utilities; OK, an uncontested lock is still fast, but not locking at
            all (where it isn't necessary) is faster. If your code *is* threaded,
            then you should probably note the risk of two calls to the *same*
            Random.Next at the same time, which may not be safe; in this case you
            could either:
            * do your own local locking in the static method
            * use StaticRandom
            * (my preferred option) give each thread a separate *instance* of the
            DiceRoller class (or whatever), so that they don't conflict and each
            has an uncontested (instance) _rand that doesn't need locking.

            In the general case, static methods should be thread safe. Looking at
            http://msdn2.microsoft.com/en-us/library/2dx6wyd4.aspx, it doesn't
            make any claims about thread-safety, so I have to assume that it isn't
            thread-safe, which means the code I posted also isn't. Oops.




            Marc


            Comment

            • Fabio Z

              #7
              Re: dice rolling problem

              "Jose Durazo" <joseN-O-S-P-A-M-@josenstacy.com ha scritto nel messaggio
              news:OkFeDSIMHH A.4888@TK2MSFTN GP02.phx.gbl...
              Hello, I'm doing an exercise to simulate rolling a pair of dice 36,000
              times, then count and display how many times the simulation rolls each
              possible sum.
              >
              For some reason each time I run my simulation, one or more of my sums is
              zero, which is highly unlikely. So I'm sure there's a bug in my code.
              But I can't tell what it is, even after re-reading it several times. Can
              someone give me a hint?
              For the truth you are rolling the same dice 72000 times, since the random
              object is always the same.

              Why you do a r.Next(1, 7) while a dice has only 6 faces?


              Comment

              • Marc Gravell

                #8
                Re: dice rolling problem

                OP>Hello, I'm doing an exercise to simulate rolling a pair of dice
                36,000
                OP>times,
                For the truth you are rolling the same dice 72000 times, since the
                random object is always the same.
                The random object being the same doesn't allow you to make this
                statement.
                Mathematically, unless the dice know about eachother and the results
                directly influence eachother, then there is no difference in rolling
                one die twice versus rolling two dice once. I think therefore that the
                OPs statement is perfectly valid. However, given I already posted the
                answer to this, you could state that "many of your successive
                observations are based on the same roll of 2 dice, themselves
                separate", meaning that the OP might have observed "1+5,1+5,...1+5 ,
                3+3, 3+3, ..., 3+3, 4+4, 4+4, ... 4+4" etc.
                Why you do a r.Next(1, 7) while a dice has only 6 faces?
                The upper number to Random.Next is exclusive; hence Next(1,7) will
                return a number in the range "[1,7)", or the set "{1,2,3,4,5,6}" .

                Marc


                Comment

                • DeveloperX

                  #9
                  Re: dice rolling problem

                  r.Next(x,y) returns a minimum of x and a maximum of < y, so in this
                  case it will return 1 to 6.

                  Fabio Z wrote:
                  "Jose Durazo" <joseN-O-S-P-A-M-@josenstacy.com ha scritto nel messaggio
                  news:OkFeDSIMHH A.4888@TK2MSFTN GP02.phx.gbl...
                  >
                  Hello, I'm doing an exercise to simulate rolling a pair of dice 36,000
                  times, then count and display how many times the simulation rolls each
                  possible sum.

                  For some reason each time I run my simulation, one or more of my sums is
                  zero, which is highly unlikely. So I'm sure there's a bug in my code.
                  But I can't tell what it is, even after re-reading it several times. Can
                  someone give me a hint?
                  >
                  For the truth you are rolling the same dice 72000 times, since the random
                  object is always the same.
                  >
                  Why you do a r.Next(1, 7) while a dice has only 6 faces?

                  Comment

                  • Marc Gravell

                    #10
                    Re: dice rolling problem

                    Ammendment; I see what you are trying to say in your "same dice 72000
                    times", but it is still incorrect; the OPs code actually rolls 36000
                    dice, each twice

                    Again, at the math level it isn't going to make the slightest damned
                    difference, but yes; to *truly* roll two dice you would need 2 Random
                    instances - however, you would need to be very careful when
                    initialising them, e.g.

                    Random dice1 = new Random(), dice2 = new Random(dice1.Ne xt());

                    A simple dice1 = new Random(), dice2 = new Random() would almost
                    always end up reporting doubles each time "1+1, 5+5, 3+3" etc due to
                    the seed and call-frequency being equal. But again: mathematically it
                    makes no distinction (1 twice versus 2 once), *provided* Random
                    provides a uniform distribution and lack-of-memory-function (i.e.
                    regardless of the first roll, the second roll is still uniform [over
                    the bigger picture; successive calls to Random are obviously
                    predictable on a 1-by-1 basis if you know the initial seed]).

                    Marc


                    Comment

                    • Fabio Z

                      #11
                      Re: dice rolling problem

                      "DeveloperX " <nntpDev@operam ail.comha scritto nel messaggio
                      r.Next(x,y) returns a minimum of x and a maximum of < y, so in this
                      case it will return 1 to 6.
                      I thinked so, but I was "deviated" by the intellisense description :)



                      Comment

                      • Fabio Z

                        #12
                        Re: dice rolling problem

                        "Marc Gravell" <marc.gravell@g mail.comha scritto nel messaggio
                        news:%23oiF2FLM HHA.4376@TK2MSF TNGP04.phx.gbl. ..
                        OP>Hello, I'm doing an exercise to simulate rolling a pair of dice 36,000
                        OP>times,
                        >
                        >For the truth you are rolling the same dice 72000 times, since the random
                        >object is always the same.
                        >
                        The random object being the same doesn't allow you to make this statement.
                        Mathematically, unless the dice know about eachother and the results
                        directly influence eachother, then there is no difference in rolling one
                        die twice versus rolling two dice once.
                        Yes, you're right, I just like OOP, so, 2 dices = 2 objects.



                        Comment

                        • Tom Leylan

                          #13
                          Re: dice rolling problem

                          I see by the thread that you fixed the original problem. If you're
                          interested in tidying up the code you see where you do the following?
                          You're forcing yourself to reset currentResult to 0 simply because you used
                          the += operator on the first assignment.

                          int currentResult = 0;
                          for (int numberOfRolls = 1; numberOfRolls <= 36000; ++numberOfRolls )
                          {
                          currentResult += r.Next(1, 7);
                          currentResult += r.Next(1, 7);
                          ++sum[currentResult];
                          currentResult = 0;
                          }

                          it could be this:

                          int currentResult = 0;
                          for (int numberOfRolls = 1; numberOfRolls <= 36000; ++numberOfRolls )
                          {
                          currentResult = r.Next(1, 7);
                          currentResult += r.Next(1, 7);
                          ++sum[currentResult];
                          }

                          this:

                          int currentResult = 0;
                          for (int numberOfRolls = 1; numberOfRolls <= 36000; ++numberOfRolls )
                          {
                          currentResult = ( r.Next(1, 7) + r.Next(1, 7) );
                          ++sum[currentResult];
                          }

                          of this eliminating currentResult altogether:

                          for (int numberOfRolls = 1; numberOfRolls <= 36000; ++numberOfRolls )
                          {
                          ++sum[ ( r.Next(1, 7) + r.Next(1, 7) ) ];
                          }

                          Re: the rolling of each die independently.. . it's a simulation you don't
                          need to make it "real" in which case you can ask for a "Next" in the range
                          of 2 to 12. There is no reason to ask for two random numbers which you then
                          add.

                          for (int numberOfRolls = 1; numberOfRolls <= 36000; ++numberOfRolls )
                          {
                          ++sum[ r.Next(2, 12) ];
                          }

                          Now modify SimulateDiceRol ls() to accept the total number of rolls as a
                          parameter (so you could change the run size) and you're all set.


                          "Jose Durazo" <joseN-O-S-P-A-M-@josenstacy.com wrote in message
                          news:OkFeDSIMHH A.4888@TK2MSFTN GP02.phx.gbl...
                          Hello, I'm doing an exercise to simulate rolling a pair of dice 36,000
                          times, then count and display how many times the simulation rolls each
                          possible sum.
                          >
                          For some reason each time I run my simulation, one or more of my sums is
                          zero, which is highly unlikely. So I'm sure there's a bug in my code.
                          But I can't tell what it is, even after re-reading it several times. Can
                          someone give me a hint?
                          >
                          Here is my code:
                          >
                          static void SimulateDiceRol ls()
                          {
                          // When you roll two dice, there are 11 possible sums:
                          // 2, 3, ..., 10, 11, 12. Define an array of 13 elements
                          // where the first two elements are unused, but the third element
                          // where index equals 2, corresponds to sum = 2, and so on.
                          // make sure they're initialized to 0, which C# does by default
                          int[] sum = new int[13];
                          >
                          // for 36,000 times, roll two dice, calculate the sum,
                          // and increment the index corresponding to that sum.
                          int currentResult = 0;
                          for (int numberOfRolls = 1; numberOfRolls <= 36000; ++numberOfRolls )
                          {
                          currentResult = RollTwoDice();
                          ++sum[currentResult];
                          }
                          >
                          // print how many times each sum comes up and what percent of the time
                          // to a 3 decimal precision that sum comes up
                          for (int sumIndex = 2; sumIndex <= 12; ++sumIndex)
                          {
                          Console.WriteLi ne("{0,5} {1,5} {2:F3}", sumIndex, sum[sumIndex],
                          (double)sum[sumIndex] / 36000 * 100);
                          }
                          }
                          >
                          // return the sum of two randomly generated integers from 1 to 6
                          // inclusive
                          static int RollTwoDice()
                          {
                          Random r = new Random();
                          return r.Next(1, 7) + r.Next(1, 7);
                          }
                          >
                          Thanks in advance,
                          Jose
                          >
                          >

                          Comment

                          • Fabio

                            #14
                            Re: dice rolling problem

                            "Tom Leylan" <tleylan@nospam .netha scritto nel messaggio
                            news:%23fi7nXOM HHA.4196@TK2MSF TNGP03.phx.gbl. ..
                            Re: the rolling of each die independently.. . it's a simulation you don't
                            need to make it "real" in which case you can ask for a "Next" in the range
                            of 2 to 12. There is no reason to ask for two random numbers which you
                            then add.
                            This is not true.
                            The sum of the different dices has not the same probability of a random
                            number between 2 to 12.
                            I.e. the most probable result of the sum is 7 because can be done with

                            1+6
                            2+5
                            3+4
                            4+3
                            5+2
                            6+1

                            the 2 and the 12 are the less probable because they can be done only with

                            1+1
                            6+6

                            For these reasons I suggested to do the 2 separated rolls.


                            Comment

                            • Brian Gideon

                              #15
                              Re: dice rolling problem


                              Marc Gravell wrote:
                              The random object being the same doesn't allow you to make this
                              statement.
                              Mathematically, unless the dice know about eachother and the results
                              directly influence eachother, then there is no difference in rolling
                              one die twice versus rolling two dice once. I think therefore that the
                              OPs statement is perfectly valid. However, given I already posted the
                              answer to this, you could state that "many of your successive
                              observations are based on the same roll of 2 dice, themselves
                              separate", meaning that the OP might have observed "1+5,1+5,...1+5 ,
                              3+3, 3+3, ..., 3+3, 4+4, 4+4, ... 4+4" etc.
                              There's no particular reason I'm mentioning this, but conditional
                              probabilities can be very difficult to explain. The Monty Hall paradox
                              is a pretty good example that demonstrates how the wording of
                              probability problems can mislead even the most astute math minds.

                              Comment

                              Working...