Random numbers: which should i be using?

  • (2 Pages)
  • +
  • 1
  • 2

20 Replies - 5175 Views - Last Post: 31 December 2012 - 02:19 PM Rate Topic: -----

#1 bboyzeez  Icon User is offline

  • D.I.C Head

Reputation: 4
  • View blog
  • Posts: 143
  • Joined: 16-December 12

Random numbers: which should i be using?

Posted 27 December 2012 - 05:34 AM

hi all,

ok here is the pieve of info i have been given from my challenge:

Use random numbers to simulate dart throwing. Get two random numbers for x and y coordinates. If (x - 0.5)2 + (y - 0.5)2 < .25, then the dart landed inside the circle.

ok then so when i use

r.Next();



everything is being missed and then when i use

r.NextDouble();



everything is being hit

surely i am missing something ?

i am then supposed to get the ratio of how many hit the circle to how many were thrown and then times it by 4 to give me an estimate of pi. i have that part sorted out its just this section where the random number is either always hitting or always missing

thanks

Is This A Good Question/Topic? 0
  • +

Replies To: Random numbers: which should i be using?

#2 sepp2k  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 2153
  • View blog
  • Posts: 3,311
  • Joined: 21-June 11

Re: Random numbers: which should i be using?

Posted 27 December 2012 - 06:17 AM

Regarding Next: If you consider the range of numbers that Next can return and think about which of those would produce which results if inserted into your formula, it should become clear why using Next will produce no hit in the vast majority of cases. That is to say of all the 231 possible values that Next can return, only one (0) would produce a hit, so of course the chance of that is pretty small.

Regarding NextDouble: I can't think of a reason why a correctly-implemented program using NextDouble would never produce a hit (other than extremely bad luck). So the most likely explanation is that you've made a mistake in your code.

This post has been edited by sepp2k: 27 December 2012 - 06:18 AM

Was This Post Helpful? 0
  • +
  • -

#3 raghav.naganathan  Icon User is offline

  • Perfectly Squared ;)
  • member icon

Reputation: 408
  • View blog
  • Posts: 1,440
  • Joined: 14-September 12

Re: Random numbers: which should i be using?

Posted 27 December 2012 - 06:21 AM

The main reason why it is happening is r.Next() gives an integer value and r.NextDouble() gives a double value.

So, lets consider an integer 1 for x and 2 for y

So, (x - 0.5)2 + (y - 0.5)2 < .25 will give a value greater than .25 and so, the condition fails. Therefore target is missed

Now consider a value like 0.7000 for x and 0.8000 for y. The equation will result in a value less than .25 and so the target will hit.

regards,
Raghav
Was This Post Helpful? 0
  • +
  • -

#4 bboyzeez  Icon User is offline

  • D.I.C Head

Reputation: 4
  • View blog
  • Posts: 143
  • Joined: 16-December 12

Re: Random numbers: which should i be using?

Posted 27 December 2012 - 06:33 AM

ye i understand the differences so it must be something in my code because i can throw 50 darts and everyone of them hits haha... ive cleaned the code up and here it is hopefully it something hard because i have looked and cannot see anything silly mistakes


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;


   public class DartsPi
    {
            
            
       private double x;
       private double y;
       private int hit;
       private int miss;

       public DartsPi()
       {
         
       }

       
       public void Throwdart()
       {
           Random r = new Random();

           x = r.NextDouble();
           y = r.NextDouble();
           
          
            double xsqaured = ((x- 0.5) * (x - 0.5));
            double ysquared = ((y - 0.5) * (y - 0.5));

            if ((xsqaured + ysquared) < 0.25)
            { hit = hit + 1; }
            else
            {miss = miss + 1;}


       }

       public void calculatepi(double a, double B)/>
       {
           double estpi = ((a / B)/> * 4);
           Console.WriteLine(" the estimate of pi is: {0}", estpi);
           Console.ReadLine();

       }
        static void Main()
        {

            Console.WriteLine("How many Darts would you like to throw? ");
            int Userdarts = int.Parse(Console.ReadLine());
            int totaldarts = Userdarts;
            DartsPi newgame = new DartsPi();
            do
            {
             
                newgame.Throwdart();
                totaldarts -= 1;

            } while ( totaldarts != 0 );

            newgame.calculatepi(newgame.hit, Userdarts);
        
            
        }
    }



Was This Post Helpful? 0
  • +
  • -

#5 sepp2k  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 2153
  • View blog
  • Posts: 3,311
  • Joined: 21-June 11

Re: Random numbers: which should i be using?

Posted 27 December 2012 - 06:37 AM

View Postraghav.naganathan, on 27 December 2012 - 02:21 PM, said:

Now consider a value like 0.7000 for x and 0.8000 for y. The equation will result in a value less than .25 and so the target will hit.


Sure, but if x is 0.9 and y is 0.8, the target will be missed. If, for a reasonable sample size, every throw results in a hit, there must be an error in the code.

@bboyzeez:

If you store your x and y values in a list somewhere and look at it afterwards, you'll probably notice that all your x values will have the same value - and so will all your y values. This is because two distinct Random objects that have been created using the same seed, will produce the same sequence of random numbers. If you create a new Random object without passing any arguments to the constructor, it will use the current system time as the seed. So if you create multiple Random objects within the same millisecond (which can easily happen in a tight loop), all those Random objects will produce the same sequence of numbers. So it won't be random at all.

To fix your issue, you should create exactly one Random object and use that one object throughout your code.

This post has been edited by sepp2k: 27 December 2012 - 06:38 AM

Was This Post Helpful? 1
  • +
  • -

#6 bboyzeez  Icon User is offline

  • D.I.C Head

Reputation: 4
  • View blog
  • Posts: 143
  • Joined: 16-December 12

Re: Random numbers: which should i be using?

Posted 27 December 2012 - 12:48 PM

View Postsepp2k, on 27 December 2012 - 06:37 AM, said:

View Postraghav.naganathan, on 27 December 2012 - 02:21 PM, said:

Now consider a value like 0.7000 for x and 0.8000 for y. The equation will result in a value less than .25 and so the target will hit.


Sure, but if x is 0.9 and y is 0.8, the target will be missed. If, for a reasonable sample size, every throw results in a hit, there must be an error in the code.

@bboyzeez:

If you store your x and y values in a list somewhere and look at it afterwards, you'll probably notice that all your x values will have the same value - and so will all your y values. This is because two distinct Random objects that have been created using the same seed, will produce the same sequence of random numbers. If you create a new Random object without passing any arguments to the constructor, it will use the current system time as the seed. So if you create multiple Random objects within the same millisecond (which can easily happen in a tight loop), all those Random objects will produce the same sequence of numbers. So it won't be random at all.

To fix your issue, you should create exactly one Random object and use that one object throughout your code.


Ok thanks I will try this later when I get home...

So without trying it and trying to understand your advice every time the loop is restarted I should start a new random and use it for the x and y , the book never talks about the current time being a seed for the random number it kinda makes more sense when I think of that :)
Was This Post Helpful? 0
  • +
  • -

#7 sepp2k  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 2153
  • View blog
  • Posts: 3,311
  • Joined: 21-June 11

Re: Random numbers: which should i be using?

Posted 27 December 2012 - 01:07 PM

View Postbboyzeez, on 27 December 2012 - 08:48 PM, said:

trying to understand your advice every time the loop is restarted I should start a new random


You should create a new Random object exactly once, at the beginning of the program. Then never again.
Was This Post Helpful? 1
  • +
  • -

#8 immeraufdemhund  Icon User is offline

  • D.I.C Regular

Reputation: 79
  • View blog
  • Posts: 495
  • Joined: 29-March 10

Re: Random numbers: which should i be using?

Posted 27 December 2012 - 10:46 PM

ugh i hate multi-touch touchpads on laptops...this is the third time i've tried to post this.

I can remember a bit ago that some languages used System Ticks to give the illusion of a random number. I think this is what you are running into. Your computer is fast enough to figure out all 50 darts. So to test a few things I made this program too.

first my results
How many Darts would you like to throw?
50
------------------------------------------
Ticks: 178766 Hits: 45 Misses: 5 Darts Thrown: 50
Ticks: 1772 Hits: 41 Misses: 9 Darts Thrown: 50
------------------------------------------
------------------------------------------
Ticks: 180606 Hits: 42 Misses: 8 Darts Thrown: 50
Ticks: 14 Hits: 40 Misses: 10 Darts Thrown: 50
------------------------------------------
------------------------------------------
Ticks: 168401 Hits: 40 Misses: 10 Darts Thrown: 50
Ticks: 14 Hits: 36 Misses: 14 Darts Thrown: 50
------------------------------------------
------------------------------------------
Ticks: 173849 Hits: 43 Misses: 7 Darts Thrown: 50
Ticks: 45 Hits: 42 Misses: 8 Darts Thrown: 50
------------------------------------------
------------------------------------------
Ticks: 175721 Hits: 41 Misses: 9 Darts Thrown: 50
Ticks: 22 Hits: 44 Misses: 6 Darts Thrown: 50
------------------------------------------
------------------------------------------
Ticks: 177943 Hits: 33 Misses: 17 Darts Thrown: 50
Ticks: 22 Hits: 41 Misses: 9 Darts Thrown: 50
------------------------------------------
------------------------------------------
Ticks: 175813 Hits: 34 Misses: 16 Darts Thrown: 50
Ticks: 17 Hits: 37 Misses: 13 Darts Thrown: 50
------------------------------------------
------------------------------------------
Ticks: 167212 Hits: 34 Misses: 16 Darts Thrown: 50
Ticks: 29 Hits: 39 Misses: 11 Darts Thrown: 50
------------------------------------------
------------------------------------------
Ticks: 173049 Hits: 34 Misses: 16 Darts Thrown: 50
Ticks: 21 Hits: 38 Misses: 12 Darts Thrown: 50
------------------------------------------
------------------------------------------
Ticks: 170857 Hits: 50 Misses: 0 Darts Thrown: 50
Ticks: 26 Hits: 42 Misses: 8 Darts Thrown: 50
------------------------------------------




now my code Program.cs
using System;

namespace CSFun
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("How many Darts would you like to throw? ");
            Random r = new Random();
            System.Diagnostics.Stopwatch sw = new Stopwatch();
            
            DartCollection mydarts = new DartCollection();
            int Userdarts = int.Parse(Console.ReadLine());
            for (int j = 0; j < 10; j++)
            {

                Console.WriteLine("------------------------------------------");
                sw.Start();
                for (int i = 0; i < Userdarts; i++)
                    mydarts.ThrowDart();
                sw.Stop();
                Console.Write("Ticks: {0} ", sw.ElapsedTicks);
                mydarts.PrintData();
                sw.Reset();
                mydarts.Clear();
                sw.Start();
                for (int i = 0; i < Userdarts; i++)
                    mydarts.ThrowDart(ref r);
                sw.Stop();
                Console.Write("Ticks: {0} ", sw.ElapsedTicks); 
                mydarts.PrintData();
                Console.WriteLine("------------------------------------------");
                mydarts.Clear();
            }

            Console.ReadLine();
        }
    }
}



DartCollection.cs
using System.Collections.ObjectModel;
namespace CSFun
{
    public class DartCollection
    {
        private Collection<Dart> darts;
        public DartCollection()
        {
            darts = new Collection<Dart>();
        }

        public void ThrowDart()
        {
            darts.Add(new Dart());
        }

        public void ThrowDart(ref System.Random r)
        {
            darts.Add(new Dart(ref r));
        }

        public void Clear()
        {
            darts.Clear();
        }
        public void PrintData()
        {
            int hits = 0;
            foreach (Dart d in darts)
            {
                if (d.Hit)
                    hits++;

                //System.Console.WriteLine(d); //uncomment to see values
            }
            System.Console.WriteLine("Hits: {0} Misses: {1} Darts Thrown: {2}", hits, darts.Count - hits, darts.Count);
        }
    }
}


Dart.cs
namespace CSFun
{
    public class Dart
    {
        public Dart()
        {
            System.Random r = new System.Random();
            System.Threading.Thread.Sleep(1);

            x = r.NextDouble();
            y = r.NextDouble();
            
        }
        public Dart(ref System.Random r)
        {
            x = r.NextDouble();
            y = r.NextDouble();
        }

        public bool Hit
        {
            get { return Calculate(); }
        }

        private bool Calculate()
        {
            double sum = OffsetSquared(x) + OffsetSquared(y);
            return sum < PROBABILITY;
        }

        private double OffsetSquared(double num)
        {
            return (num - 0.5) * (num - 0.5);
        }

        public override string ToString()
        {
            string text = Hit ? "Hit" : "Missed";
            return string.Format("Dart: [{0},{1}] - {2}", x,y, text);
        }

        public readonly double x;
        public readonly double y;
        private const double PROBABILITY = 0.25;
    }
}


i find it interesting that if i create a new instance of Random I have to add a Thread.Sleep. Not very nice but it does work. Or I can pass in the reference of Random from Program and it also works. Which that got me curious how much time is wasted passing a reference as opposed to creating a new instance and sleeping for 1ms... well the numbers don't lie...LOTS! but it gives random numbers.

And if i take out the sleep(1) then my ticks goes down to ~300 which is still lots of extra cycles.

Maybe someone can suggest a more elequent way of passing around Random in this case. Just thought I'd share my results
Was This Post Helpful? 0
  • +
  • -

#9 Momerath  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 1012
  • View blog
  • Posts: 2,444
  • Joined: 04-October 09

Re: Random numbers: which should i be using?

Posted 28 December 2012 - 12:04 AM

Don't pass it around at all. The class that needs to use it should be the one generating it. If you need random numbers in multiple classes, consider using the singleton pattern.
Was This Post Helpful? 0
  • +
  • -

#10 bboyzeez  Icon User is offline

  • D.I.C Head

Reputation: 4
  • View blog
  • Posts: 143
  • Joined: 16-December 12

Re: Random numbers: which should i be using?

Posted 28 December 2012 - 04:25 AM

ahh yes i realise now :) i put the new random object at beginning and then run the program 50 darts thrown and 35 hit so thats more like it :) thanks everyone for being helpful.

btw when you wrote add the numbers to a list i havent got that far yet :) is that to do with arrays ?
Was This Post Helpful? 0
  • +
  • -

#11 immeraufdemhund  Icon User is offline

  • D.I.C Regular

Reputation: 79
  • View blog
  • Posts: 495
  • Joined: 29-March 10

Re: Random numbers: which should i be using?

Posted 28 December 2012 - 06:31 AM

View Postbboyzeez, on 28 December 2012 - 06:25 AM, said:

btw when you wrote add the numbers to a list i havent got that far yet :)/> is that to do with arrays ?


Yes

@Momerath

Quote

Don't pass it around at all. The class that needs to use it should be the one generating it. If you need random numbers in multiple classes, consider using the singleton pattern.

If you look at my code I do both. I have one method of Throw dart that passes a Random object around, and one with no parameters. It uses the no parameter constructor of Dart. that constructor creates a new Random spits out x and y and that is it. If I the OP would do as you said litterally (like I did in Dart.cs) then he would still have his problem of the Random number not being random. So in this case it does need to be passed. it saves on ticks, and I would imagine on memory (although I haven't tested that)

Maybe you could show us your singleton example with your results of ticks.
Was This Post Helpful? 0
  • +
  • -

#12 CodingSup3rnatur@l-360  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 992
  • View blog
  • Posts: 972
  • Joined: 30-September 10

Re: Random numbers: which should i be using?

Posted 28 December 2012 - 07:57 AM

In your code, for the case where the caller uses the default constructor, you could just use a single static readonly variable to hold a single instance of the Random class in the Dart class.

Alternatively, you could use another class that manages the Random instance, and always returns the same instance of Random (in a singleton like manner) when asked for an instance. You can then use that when the default constructor is called to get your Random object.

The second option probably being the better of the two. Either way, you wouldn't need that horrible Thread.Sleep() then :)/>

Also, the use of the ref keyword doesn't seem to be serving any purpose in your code.

EDIT 1:

You obviously have to be careful if you introduce multiple threads though, when using a static variable to hold the Random object. You could overcome this problem by making the Random instance thread local.

EDIT 2:

In a real, non trivial program, if a class genuinely needs to generate it's own random numbers, I like the idea, from a design point of view, of making that dependency explicit, and injecting the random number generator (either the built in one, or a custom wrapper or implementation) into the class via the constructor. How exactly you manage the creation of Random instance(s) to prevent the perceived randomness from degrading really depends on the situation.

This post has been edited by CodingSup3rnatur@l-360: 28 December 2012 - 10:44 AM
Reason for edit:: Note about thread safety + Note about injecting the Random number generator + Singleton + Spelling

Was This Post Helpful? 1
  • +
  • -

#13 immeraufdemhund  Icon User is offline

  • D.I.C Regular

Reputation: 79
  • View blog
  • Posts: 495
  • Joined: 29-March 10

Re: Random numbers: which should i be using?

Posted 28 December 2012 - 04:30 PM

yeah it was late last night when I was programming that example. I looked at it this morning and am suprised it compiled at all :)

Now that you mention it i bet if i had used a static Random member it would have worked. And if my baby wasn't crying her head off I'd try it... but she is. Oh well that is what the edit button is for.
Was This Post Helpful? 0
  • +
  • -

#14 bboyzeez  Icon User is offline

  • D.I.C Head

Reputation: 4
  • View blog
  • Posts: 143
  • Joined: 16-December 12

Re: Random numbers: which should i be using?

Posted 30 December 2012 - 08:13 AM

ok i know this is different to the original post but seeing as ticks was mentioned in here i thought it post it here save making a new thread and upsetting people:)

so i have a challenege which is to modify an exsiting program to add two ticks in one before a loop and one after to see how long it takes to complete the loop.

 public static void Main()
    {
        int[] score = ReadIntArray();
        ReverseInputArray r = new ReverseInputArray(score);
        r.Display("The original array is ");
        ReverseInputArray s = new ReverseInputArray(score);
        int starttime = System.Environment.TickCount;
        s.Reverse(0, score.Length - 1);
        int stoptime = System.Environment.TickCount;
        int totaltime = stoptime - starttime;
        Console.WriteLine(" the time used in milliseconds is {0}", stoptime - starttime);
        r.Display("The reversed array is ");
        Console.ReadLine();
    }



now i put a break in on line 10 to check my startt and stop times are different which end up being the same times, even though if i hover mouse over the tickcount in line 7 and then in line 9 both are different

any ideas why they are different but come up as same when i run program?

thanks
Was This Post Helpful? 0
  • +
  • -

#15 Skydiver  Icon User is online

  • Code herder
  • member icon

Reputation: 3662
  • View blog
  • Posts: 11,466
  • Joined: 05-May 12

Re: Random numbers: which should i be using?

Posted 30 December 2012 - 01:59 PM

As per MSDN:

Quote

System.Environment.TickCount is the number of milliseconds since the system has started.


Here "system" refers to the operating system. It is not the number of milliseconds since your program has started which seems to be what you are expecting.

If you want numbers that aren't based on the system time, consider using the abstraction offered by the Stopwatch class. http://msdn.microsof....Stopwatch.aspx
Was This Post Helpful? 0
  • +
  • -

  • (2 Pages)
  • +
  • 1
  • 2