True random is not true random I am really confused - c#

Alright I tested the way below.
Generated x times random numbers between 0~x and then checked the ones that were not generated.
I would assume that it would be very close to 100%. What I mean is all numbers between 0~x are generated.
But results are shocking. About 36% of the numbers are missing.
Is my random function not really random?
Here below my random class:
private static Random seedGenerator = new Random();
private static ThreadLocal<Random> random =
new ThreadLocal<Random>(SeededRandomFactory);
private static Random SeededRandomFactory()
{
lock (seedGenerator)
return new Random(seedGenerator.Next());
}
public static int GenerateRandomValueMin(int irRandValRange, int irMinValue)
{
return random.Value.Next(irMinValue, irMinValue + irRandValRange);
}
Here the below results:
Between 0-10, missing numbers count: 4, percent: 40%
Between 0-100, missing numbers count: 36, percent: 36%
Between 0-1000, missing numbers count: 369, percent: 36,9%
Between 0-10000, missing numbers count: 3674, percent: 36,74%
Between 0-100000, missing numbers count: 36583, percent: 36,58%
Between 0-1000000, missing numbers count: 367900, percent: 36,79%
Between 0-10000000, missing numbers count: 3678122, percent: 36,78%
Between 0-100000000, missing numbers count: 36797477, percent: 36,8%
Here the code how I check:
File.WriteAllText("results.txt", "");
int irFirst = 10;
for (int i = 0; i < 8; i++)
{
HashSet<int> hsGenerated = new HashSet<int>();
for (int k = 0; k < irFirst; k++)
{
hsGenerated.Add(GenerateRandomValue.GenerateRandomValueMin(irFirst, 0));
}
int irNotFound = 0;
for (int k = 0; k < irFirst; k++)
{
if (hsGenerated.Contains(k) == false)
irNotFound++;
}
string srSonuc =
string.Format(
"Between 0-{0}, missing numbers count: {1}, percent: {2}%",
irFirst, irNotFound,
Math.Round((Convert.ToDouble(irNotFound)/Convert.ToDouble(irFirst))*100.0, 2).ToString()
);
using (StreamWriter w = File.AppendText("sonuclar.txt"))
{
w.WriteLine(srSonuc);
}
irFirst = irFirst * 10;
}

As mentioned in the comments, your testing method is off.
You draw x times a number between 0 and x. The probability that a specific number is not drawn is:
As x approaches infinity, p will go towards 1/e (or approx. 36.7879441%) And this is the number you are seeing in your results.
Also, as x approaches infinity, you will observe this probability as outcome of your sample (Law of large numbers)
This has to do with probability. When you have a bowl with a red and a white marble. And you take one, put it back an take another one you cannot guarantee that you see both. You could take the red one twice. You are doing the same thing with more objects.
To elaborate on true true randomness:
I would expect close to 99% percent instead of 64%. Or at least 90%+ percent. So you say this isn't possible with current technology
That is simple. Thanks to modern math, technology and my super powers I can tell you how to do that: You need more draws than numbers to choose from. The formula becomes:
where n is you desired percentage of missing numbers. For example if you are willing to accept 5% numbers missing, you must draw three times as many random numbers. For a 1% chance, you need to iterate 4.6 times the maximum number.
This math assumes a perfectly uniform random number generation.

Your results are exactly what is to be expected from a uniform distribution where you sample with replacement.
Consider the simplest possible example. You have a coin and toss it twice. So we assume that we are sampling from a uniform discrete distribution.
The possible outcomes, which occur with equal probability of 0.25 are:
TT
TH
HT
HH
As you can see, only two of the four outcomes have both heads and tails.
This is known as sampling with replacement. So, once we have sampled a tails, then we "put it back in the bag", and it could come out again on the next sample.
Now suppose we sample without replacement. In that case there are two possible outcomes:
TH
HT
And as you see, each possible value appears exactly once.
Essentially your expectation for the results is not correct. As another example, suppose you toss a coin and it comes down tails. What do you expect will happen on the next toss. You are arguing that the coin must now come down heads. But that is clearly nonsense.
If you did want to sample without replacement, and it's not clear that's really what you want, then you do so with the Fisher-Yates shuffle.

If you want 100 million unique random number you could do something like this:
Now using Fisher-Yates suffle algorithm:
List<int> numbers = new List<int>(100000000);
for (int i = 0; i < numbers.Capacity; i++)
{
int rnd = random.Next(numbers.Count + 1);
if (rnd == numbers.Count)
numbers.Add(i);
else
{
numbers.Add(numbers[rnd]);
numbers[rnd] = i;
}
}
By the way you could calculate irNotFound much faster:
int irNotFound = irFirst - hsGenerated.Count;
Good luck with your quest.

Related

Why is the pseudo-random number generator less likely to generate 54 big numbers in a row?

Consider an event that occurs with probability p. This program checks how many failed trials it takes before the event occurs and keeps a histogram of the totals. e.g.: If p were 0.5, then this would be like asking how many times in a row a coin comes up tails before it comes up heads? With smaller values of p, we would expect many failures before we get a success.
The implementation being tested is essentially: while (!(rand.NextDouble() < p)) count++;
Here is a plot of the histogram of outcomes for count.
Immediately obvious is the irregularity at x=54. For some reason, it is approximately half as likely as it should be for a series of exactly 54 random numbers greater than or equal to p to be generated in a row.
The actual p I'm checking in this test is 1/32. (Doesn't really matter, as long as it's small enough to get some measurable number of 54's as an outcome.) And I'm counting 10000000 total successes. (Also doesn't seem to matter.) It also doesn't matter what random seed I use.
Obviously this is a quirk of the pseudo-random number generator being used by the Random.NextDouble function in .NET. But I'd like to know why does this otherwise uniform data have such a striking single spike in such an oddly specific and consistent place? What is it about this particular pseudo-random number generator that makes generating exactly 54 large numbers in a row followed by a small number half as likely as any other sequence length?
I would have expected many more non-uniform anomalies as it degenerates, not just this one spike.
Here is the code that generated this data set:
using System;
namespace RandomTest
{
class Program
{
static void Main(string[] args)
{
Random rand = new Random(1);
int numTrials = 10000000;
int[] hist = new int[512];
double p = 1.0 / 32.0;
for (int i = 0; i < numTrials; ++i) {
int count = 0;
while (!(rand.NextDouble() < p)) {
count++;
}
if (count > hist.Length - 1) {
count = hist.Length - 1;
}
hist[count]++;
}
for (int i = 0; i < hist.Length; ++i) {
Console.WriteLine("{0},{1}", i, hist[i]);
}
}
}
}
In case it's relevant, this is .Net Framework 4.7.2 on Windows x86.
I ran your code on framework 4.8 and I got point 28 to be the outlier
plot of generated data
Then I ran it again without any changes, and 58 was the outlier
2nd plot of data
My Guess as to the cause of the issue you perceive is that the random generator is random.
Running the code yields different results each time, and it appears to be random where the outlier is.
Since we know that the outlier is random, we can conclude that it is not a fault in a specific line of code. Because of this we can assume that the random outlier could be caused by mere chance that the generator picked a number significantly less than others. The randomness of randomness.

Why is there a strong correlation between random number and correct guesses?

In trying to test whether knowing the history of a random number could help predict the future results, I found a strong, unexpected correlation between the average of the number generated, and the number of correct guesses.
The test was supposed to simulate flipping a coin (heads = 0, tails = 1) and if previous attempts were biased towards heads then guess tails and vice versa.
Why is the sum of the generated numbers always nearly equal to the number of correct guesses in the following LinqPad program?
void Main()
{
var rnd = new Random();
var attempts = 10000000;
var correctGuesses = 0;
long sum = 0;
decimal avg = 0.5m;
for (int i = 0; i < attempts; i++)
{
var guess = avg < 0.5m ? 1 : 0;
var result = rnd.Next(0, 2);
if (guess == result)
{
correctGuesses += 1;
}
sum += result;
avg = (decimal)sum/(decimal)attempts;
}
attempts.Dump("Attempts");
correctGuesses.Dump("Correct Guesses");
avg = (decimal)sum / (decimal)attempts;
avg.Dump("Random Number Average");
}
Have a made an error in the code? Is this a natural relationship? I expected the averages to converge at 0.5 as I increased the number of attempts because the distribution is fairly even - I tested this with 10bn calls to Random.Next(0,2) - but I did not expect the sum of generated numbers to correlate to the number of correct guesses.
Your error is this line:
avg = (decimal)sum/(decimal)attempts;
Makes no sense to divide the sum (based over i to that point) by attempts. Divide by i (EDIT: more precisely i+1) instead for avg to give you something meaningful.
The Random class, without a seed, generates a random number using the current time as seed, meaning that a call of the rnd.Next method in your cycle will result in the same number several times over, depending on how fast your machine goes through the cycle.

Random number distribution is uneven / non uniform

I have noticed a strange issue with the random number generation in c#, it looks like sets (patterns) are repeated a lot more often than you would expect.
I'm writing a mechanism that generates activation codes, a series of 7 numbers (range 0-29).
Doing the math, there should be 30^7 (22billion) possible combinations of activation codes. Based on this it should be extremely unlikely to get a duplicate activation code before the 1 billionth code is generated. However running my test, I start getting duplicate codes after about 60,000 iteration, which is very surprising. I have also tried using RNGCryptoServiceProvider with similar results, I get duplicates at about 100,000 iterations.
I would really like to know if this is a bug/limitation of the random number generation in .Net or if I'm doing something wrong.
The following code is a test to validate the uniqueness of the generated codes:
static void Main(string[] args)
{
Random rand = new Random();
RandomActivationCode(rand, true);
Console.Out.WriteLine("Press enter");
Console.ReadLine();
}
static void RandomActivationCode(Random randomGenerator)
{
var maxItems = 11000000;
var list = new List<string>(maxItems);
var activationCodes = new HashSet<string>(list);
activationCodes.Clear();
DateTime start = DateTime.Now;
for (int i = 0; i < maxItems; ++i)
{
string activationCode = "";
for (int j = 0; j < 7; ++j)
{
activationCode += randomGenerator.Next(0,30) + "-";
}
if (activationCodes.Contains(activationCode))
{
Console.Out.WriteLine("Code: " + activationCode);
Console.Out.WriteLine("Duplicate at iteration: " + i.ToString("##,#"));
Console.Out.WriteLine("Press enter");
Console.ReadLine();
Console.Out.WriteLine();
Console.Out.WriteLine();
}
else
{
activationCodes.Add(activationCode);
}
if (i % 100000 == 0)
{
Console.Out.WriteLine("Iteration: " + i.ToString("##,#"));
Console.Out.WriteLine("Time elapsed: " + (DateTime.Now - start));
}
}
}
My workaround is to use 10 number activation codes, which means that the test runs without any duplicate values being generated. The test runs up to 11 million iterations (after which point it runs out of memory).
This is not at all surprising; this is exactly what you should expect. Your belief that it should take a long time to generate duplicates when the space of possibilities is large is simply false, so stop believing that. Start believing the truth: that if there are n possible codes then you should start getting duplicates at about the square root of n codes generated, which is about 150 thousand if n is 22 billion.
Think about it this way: by the time you have generated root-n codes, most of them have had roughly a root-n-in-n chance to have a collision. Multiply root-n by roughly root-n-in-n, and you get... roughly 100% chance of collision.
That is of course not a rigorous argument, but it should give you the right intution, to replace your faulty belief. If that argument is unconvincing then you might want to read my article on the subject:
http://blogs.msdn.com/b/ericlippert/archive/2010/03/22/socks-birthdays-and-hash-collisions.aspx
If you want to generate a unique code then generate a GUID; that's what they're for. Note that a GUID is not guaranteed to be random, it is only guaranteed to be unique.
Another choice for generating random seeming codes that are not actually random at all, but are unique, is to generate the numbers 1, 2, 3, 4, ... as many as you want, and then use the multiplicative inverse technique to make a random-looking unique encoding of those numbers. See http://ericlippert.com/2013/11/14/a-practical-use-of-multiplicative-inverses/ for details.

Random Probability Selection

Say I have 10 prizes to give to 100 people. Each person gets a shot, one at a time. So if the first person fails to win a prize, the probability goes up, 10 in 99, and so one... Also all 10 prizes MUST go.
What would be the best way to write this in such a way that by the end if there is still a prize left, that person would have a 1 in 1 chance to get a prize...
What I was thinking like this:
int playersLeft = 100
int winners = 0
while (winners < 10)
winners += (random.Next(playersLeft--)<(10-winners)) ? 1 : 0;
I wanted to know if there was a better or more straight forward way to do it. I know it seems simple but this simple task is part of a very important aspect of the app and it must be right.
TO CLARIFY: Why I want to do something like this:
In reality there is an unlimited number of players, each with an X in Y probability to win, say 10/100 = 10%. However if I leave it to the random number generator, there is a chance that in 100 players, only 9 would win, or worst, 11. In my app, I must assure that no more and no less than 10 players for every 100 will win.
Should every person have equal chances of winning? In that case why not just select randomly 10 distinct numbers 1-100 and then pretend to do it in order?
var winners = new HashSet<int>();
while(winners.Count < 10)
{
var number = random.Next(100);
if(!winners.Contains(number)) winners.Add(number);
}
for(i = 0; i < 100; i++)
{
if(winners.Contains(i)) Console.WriteLine("{0} won!!!", i);
else Console.WriteLine("{0} didn't win, sorry...", i);
}
I have thought about this some more and have come up with the following. We can give the first guy a fair shot at winning and then if the rest of the rewards are distributed fairly among the rest of the people (no matter if he wins or loses) the whole thing will be fair. Of course that's far from formal proof, so feel free to correct me. The following should give a fair system:
int prizes = 10;
for(int i = 100; i >= 1; i++)
{
var result = random.Next(people);
if(result < prizes)
{
Console.WriteLine("{0} won", i);
prizes--;
}
}
Edit: Proof this works:
The first person trivially has n/k chance of winning (n being the number of prizes, k being the number of people.
Let's assume we distribute the remaining prizes fairly among the rest of the people. In that case they will have with probability n/k, n-1 prizes distributed between them and with probability (k-n)/k, n prizes. That adds up to (n*(n-1))/k + (n*(k-n))/k = n*(k-1)/k on average which is their fair share of the prizes.
We use the same method to either distribute n-1 or n prizes among the k-1 people. Q.E.D.
This will give you the behavior of forcing the probability of a winner to go to 1.0 as the number of people shrinks. However, as #obrok pointed out, the probability of a person winning a prize depends on their rank in the list of 100 people.
This is actually the same algorithm that is used for "N choose K" subset selection. http://mcherm.com/permalinks/1/a-random-selection-algorithm
int prizes = 10;
int people = 100;
while ( prizes > 0 ) {
double probOfWin = (double) prizes / people;
if ( random.NextDouble() <= probOfWin ) {
prizes--;
}
people--;
}
The perfectly fair way to do is to generate a random number from 1 to (100! / (90! * 10!)) (since this is the number of possible combinations of prizewinners) and use that to award the prizes.
However it's easier to use some multiple of that number, such as the number of permutations of prizewinners, which is (100! / 90!). One way of doing this is to populate an array of 100 integers but remove the winning integer from the array each time (swapping it with the last non-winning integer is the easiest way to achieve this).
Your algorithm effectively requires randomness of 100! so it is much less efficient, although I believe it is still perfectly fair.

Efficient algorithm to get primes between two large numbers

I'm a beginner in C#, I'm trying to write an application to get primes between two numbers entered by the user. The problem is: At large numbers (valid numbers are in the range from 1 to 1000000000) getting the primes takes long time and according to the problem I'm solving, the whole operation must be carried out in a small time interval. This is the problem link for more explanation:
SPOJ-Prime
And here's the part of my code that's responsible of getting primes:
public void GetPrime()
{
int L1 = int.Parse(Limits[0]);
int L2 = int.Parse(Limits[1]);
if (L1 == 1)
{
L1++;
}
for (int i = L1; i <= L2; i++)
{
for (int k = L1; k <= L2; k++)
{
if (i == k)
{
continue;
}
else if (i % k == 0)
{
flag = false;
break;
}
else
{
flag = true;
}
}
if (flag)
{
Console.WriteLine(i);
}
}
}
Is there any faster algorithm?
Thanks in advance.
I remember solving the problem like this:
Use the sieve of eratosthenes to generate all primes below sqrt(1000000000) = ~32 000 in an array primes.
For each number x between m and n only test if it's prime by testing for divisibility against numbers <= sqrt(x) from the array primes. So for x = 29 you will only test if it's divisibile by 2, 3 and 5.
There's no point in checking for divisibility against non-primes, since if x divisible by non-prime y, then there exists a prime p < y such that x divisible by p, since we can write y as a product of primes. For example, 12 is divisible by 6, but 6 = 2 * 3, which means that 12 is also divisible by 2 or 3. By generating all the needed primes in advance (there are very few in this case), you significantly reduce the time needed for the actual primality testing.
This will get accepted and doesn't require any optimization or modification to the sieve, and it's a pretty clean implementation.
You can do it faster by generalising the sieve to generate primes in an interval [left, right], not [2, right] like it's usually presented in tutorials and textbooks. This can get pretty ugly however, and it's not needed. But if anyone is interested, see:
http://pastie.org/9199654 and this linked answer.
You are doing a lot of extra divisions that are not needed - if you know a number is not divisible by 3, there is no point in checking if it is divisible by 9, 27, etc. You should try to divide only by the potential prime factors of the number. Cache the set of primes you are generating and only check division by the previous primes. Note that you do need to generate the initial set of primes below L1.
Remember that no number will have a prime factor that's greater than its own square root, so you can stop your divisions at that point. For instance, you can stop checking potential factors of the number 29 after 5.
You also do can increment by 2 so you can disregard checking if an even number is prime altogether (special casing the number 2, of course.)
I used to ask this question during interviews - as a test I compared an implementation similar to yours with the algorithm I described. With the optimized algorithm, I could generate hundreds of thousands of primes very fast - I never bothered waiting around for the slow, straightforward implementation.
You could try the Sieve of Eratosthenes. The basic difference would be that you start at L1 instead of starting at 2.
Let's change the question a bit: How quickly can you generate the primes between m and n and simply write them to memory? (Or, possibly, to a RAM disk.) On the other hand, remember the range of parameters as described on the problem page: m and n can be as high as a billion, while n-m is at most a million.
IVlad and Brian most of a competitive solution, even if it is true that a slower solution could be good enough. First generate or even precompute the prime numbers less than sqrt(billion); there aren't very many of them. Then do a truncated Sieve of Eratosthenes: Make an array of length n-m+1 to keep track of the status of every number in the range [m,n], with initially every such number marked as prime (1). Then for each precomputed prime p, do a loop that looks like this:
for(k=ceil(m/p)*p; k <= n; k += p) status[k-m] = 0;
This loop marks all of the numbers in the range m <= x <= n as composite (0) if they are multiple of p. If this is what IVlad meant by "pretty ugly", I don't agree; I don't think that it's so bad.
In fact, almost 40% of this work is just for the primes 2, 3, and 5. There is a trick to combine the sieve for a few primes with initialization of the status array. Namely, the pattern of divisibility by 2, 3, and 5 repeats mod 30. Instead of initializing the array to all 1s, you can initialize it to a repeating pattern of 010000010001010001010001000001. If you want to be even more cutting edge, you can advance k by 30*p instead of by p, and only mark off the multiples in the same pattern.
After this, realistic performance gains would involve steps like using a bit vector rather than a char array to keep the sieve data in on-chip cache. And initializing the bit vector word by word rather than bit by bit. This does get messy, and also hypothetical since you can get to the point of generating primes faster than you can use them. The basic sieve is already very fast and not very complicated.
One thing no one's mentioned is that it's rather quick to test a single number for primality. Thus, if the range involved is small but the numbers are large (ex. generate all primes between 1,000,000,000 and 1,000,100,000), it would be faster to just check every number for primality individually.
There are many algorithms finding prime numbers. Some are faster, others are easier.
You can start by making some easiest optimizations. For example,
why are you searching if every number is prime? In other words, are you sure that, given a range of 411 to 418, there is a need to search if numbers 412, 414, 416 and 418 are prime? Numbers which divide by 2 and 3 can be skipped with very simple code modifications.
if the number is not 5, but ends by a digit '5' (1405, 335), it is not prime bad idea: it will make the search slower.
what about caching the results? You can then divide by primes rather by every number. Moreover, only primes less than square root of the number you search are concerned.
If you need something really fast and optimized, taking an existing algorithm instead of reinventing the wheel can be an alternative. You can also try to find some scientific papers explaining how to do it fast, but it can be difficult to understand and to translate to code.
int ceilingNumber = 1000000;
int myPrimes = 0;
BitArray myNumbers = new BitArray(ceilingNumber, true);
for(int x = 2; x < ceilingNumber; x++)
if(myNumbers[x])
{
for(int y = x * 2; y < ceilingNumber; y += x)
myNumbers[y] = false;
}
for(int x = 2; x < ceilingNumber; x++)
if(myNumbers[x])
{
myPrimes++;
Console.Out.WriteLine(x);
}
Console.Out.WriteLine("======================================================");
Console.Out.WriteLine("There is/are {0} primes between 0 and {1} ",myPrimes,ceilingNumber);
Console.In.ReadLine();
I think i have a very fast and efficient(generate all prime even if using type BigInteger) algorithm to getting prime number,it much more faster and simpler than any other one and I use it to solve almost problem related to prime number in Project Euler with just a few seconds for complete solution(brute force)
Here is java code:
public boolean checkprime(int value){ //Using for loop if need to generate prime in a
int n, limit;
boolean isprime;
isprime = true;
limit = value / 2;
if(value == 1) isprime =false;
/*if(value >100)limit = value/10; // if 1 number is not prime it will generate
if(value >10000)limit = value/100; //at lest 2 factor (not 1 or itself)
if(value >90000)limit = value/300; // 1 greater than average 1 lower than average
if(value >1000000)limit = value/1000; //ex: 9997 =13*769 (average ~ sqrt(9997) is 100)
if(value >4000000)limit = value/2000; //so we just want to check divisor up to 100
if(value >9000000)limit = value/3000; // for prime ~10000
*/
limit = (int)Math.sqrt(value); //General case
for(n=2; n <= limit; n++){
if(value % n == 0 && value != 2){
isprime = false;
break;
}
}
return isprime;
}
import java.io.*;
import java.util.Scanner;
class Test{
public static void main(String args[]){
Test tt=new Test();
Scanner obj=new Scanner(System.in);
int m,n;
System.out.println(i);
m=obj.nextInt();
n=obj.nextInt();
tt.IsPrime(n,m);
}
public void IsPrime(int num,int k)
{
boolean[] isPrime = new boolean[num+1];
// initially assume all integers are prime
for (int i = 2; i <= num; i++) {
isPrime[i] = true;
}
// mark non-primes <= N using Sieve of Eratosthenes
for (int i = 2; i*i <= num; i++) {
// if i is prime, then mark multiples of i as nonprime
// suffices to consider mutiples i, i+1, ..., N/i
if (isPrime[i]) {
for (int j = i; i*j <=num; j++) {
isPrime[i*j] = false;
}
}
}
for (int i =k; i <= num; i++) {
if (isPrime[i])
{
System.out.println(i);
}
}
}
}
List<int> prime(int x, int y)
{
List<int> a = new List<int>();
int b = 0;
for (int m = x; m < y; m++)
{
for (int i = 2; i <= m / 2; i++)
{
b = 0;
if (m % i == 0)
{
b = 1;
break;
}
}
if (b == 0) a.Add(m)`
}
return a;
}

Categories

Resources