I've created a program that use rand() to generate repeated number in C.
However the repeated number doesn't follow Central Limit Theorem
Can anyone solve this rand() bug problem or is there an alternative other than using rand() C library to generate better random number?
Here's the screen shot:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <windows.h>
#define TOTAL_THROW 10000000
typedef enum _COINTOSS {
UNDEFINED = 0,
HEAD = 1,
TAIL = 2
} COINTOSS;
COINTOSS toss_coin () {
int x = rand() % 2;
if (x == 0) return HEAD;
else if (x == 1) return TAIL;
}
void main () {
int x, i, j, v1 = 0, v2 = 200, total = 0;
int head_range[25] = {0};
int tail_range[25] = {0};
int no_range = 0;
int count = 0;
int repeated = 0;
COINTOSS previos_toss = UNDEFINED;
COINTOSS current_toss;
srand(time(NULL));
for (i=0; i<TOTAL_THROW; i++) {
current_toss = toss_coin(); // current toss
if (previos_toss == current_toss) {
count++;
} else {
if (current_toss == HEAD) head_range[count] += 1;
else if (current_toss == TAIL) tail_range[count] += 1;
previos_toss = current_toss;
count = 0;
}
}
for (i=24; i>=0; i--) {
printf("+%d = %d\n", i+1, head_range[i]);
}
puts("________________\n");
for (i=0; i<25; i++) {
printf("-%d = %d\n", i+1, tail_range[i]);
}
printf("\nTOTAL_THROW: %d\n", TOTAL_THROW);
printf("\nPress [ENTER] to exit. . .");
getchar();
}
Your problem is using modulus to get your random number into the required range, which uses the lower bits (it's a classic gotcha):
int x = rand() % 2;
The lower bits of rand() (a linear congruential generator (LCG)) are not as random as the high bits. This applies to all LCG's regardless of library or language.
For a range of [0..N), you should do something like this (which uses the high bits):
int r = rand() / ( RAND_MAX / N + 1 );
Related
I have a program that looks something like this. i would like to run my if else query by probability.
int main() {
int probability = 70; //<-- 70% probability to run if statement
for (int i = 0; i < 5e5; i++){
if (???){
...
}
else {
...
}
}
return 0;
}
As #user3386109 pointed out, if(rand() % 100 < chance) is probably more then sufficient. As explained in the C FAQ, when the random number generated is not a multiple of 100, here, this method causes some numbers to appear more than others. If it falls on the range where it makes a difference, the easiest thing is to draw another number.
#include <stdio.h>
#include <stdlib.h> /* rand() */
#include <time.h> /* clock() */
/** http://c-faq.com/lib/randrange.html */
static int rand_0_99(void) {
unsigned int x = (RAND_MAX + 1u) / 100;
unsigned int y = x * 100;
unsigned int r;
do r = rand();
while(r >= y);
return r / x;
}
int main(void) {
size_t i, cumulate = 0;
const size_t replicas = 1000000;
const int chance_100 = 70;
/* Seed the linear congruential generator with the time. */
srand((unsigned)clock());
for(i = 0; i < replicas; i++) {
const int decision = rand_0_99() < chance_100;
if(decision) cumulate++;
}
printf("P(r < %d/100) = %lu/%lu\n",
chance_100, (unsigned long)cumulate, (unsigned long)replicas);
return EXIT_SUCCESS;
}
This is overkill, but may be needed, especially when 100 is close to RAND_MAX.
I am currently on my Uni homework and this is the last task. Its the 14th euler problem.
https://projecteuler.net/problem=14
So I am really new and i know that have a lot of crappy implementations. When executing this there is actually no output at all. I've been running this for 3 Minutes because i thought it needed to "load"..
My Task is to have a working function that calculates the Length and then take this length and compare it to have the longest chain as the "Final" output.
I tried to have a Loop that calculates the length for every i in 1000000 and then save this number into an array with the same size.
At the end of the Loop I want to compare the last length with the current and save the longer into the var if its longer.
I am stuck for like the past 2 hours
Here is my current Code:
#include <stdio.h>
#include <math.h>
int number = 1000000;
long sequence = 0;
int seqLen = 0;
int startingNum = 0;
int currLen = 0;
unsigned calculateCollatzLength(unsigned n){
int ans = 1;
while (n != 1) {
if (n & 1) {
n = 3 * n + 1;
} else {
n >>= 1;
}
ans ++;
}
currLen = ans;
return currLen;
}
int main() {
int cache[number];
for(int i = 0; i <= number; i++){
calculateCollatzLength(i);
cache[i] = currLen;
if (cache[i] > seqLen) {
seqLen = cache[i];
startingNum = i;
}
}
printf("The Longest Collatz Chain from 1 to 1000000 is %d long and has the starting number %d \n", seqLen, startingNum);
}
Hope that this is kind of understandable to ask in on this since this is my 3rd Question and it kind of feels like cheating asking but i dont know who to ask or cant find any answers :(
Here's a cleaned-up working version of your code. There's no need for a cache, and int64_t is a safer bet than unsigned (which is likely to be 32 bits) to avoid overflows. Your use of global variables was confusing and unnecessary – you can simply return the length of the sequence and find the maximum in main.
#include <stdio.h>
#include <stdint.h>
int collatz(int64_t n){
int len = 1;
while (n != 1) {
if (n & 1) {
n = 3 * n + 1;
} else {
n >>= 1;
}
len++;
}
return len;
}
#define N 1000000
int main(void) {
int longest_i = 0;
int longest = 0;
for(int i = 1; i <= N; i++){
int len = collatz(i);
if (len > longest) {
longest_i = i;
longest = len;
}
}
printf("**collatz(%d) = %d\n", longest_i, longest);
}
I can get the random numbers into an array but I can't figure out how to check to make sure that they aren't repeating. I print out the code but there are no numbers in the array (prints out nothing).
//puts random numbers into an array
i = 0, j = 0;
srand(time(NULL));
for (i = 0; i < arrSize; i++)
{
randArr[i] = randNums(1,50);
}
i = 0;
for(i = 0; i < arrSize; i++)
{
printf("%d ", randArr[i]);
}
printf("\n\n");
//checks to make sure there are no duplicates
i = 0, j = 0, k = 0, temp = 0;
for (i = 0; i < arrSize; i++)
{
for (j = 1; j <= arrSize;)
{
if (randArr[j] == randArr[i])
{
for (k = j; k <= arrSize; k++)
{
temp = randNums(1,50);
randArr[k + 1] = temp;
}
arrSize--;
}
else
j++;
}
}
//generates random numbers between the inputed max and min
int randNums(int min, int max)
{
int result = 0, low = 0, high = 0;
if (min < max)
{
low = min;
high = max + 1;
}
else
{
low = max + 1;
high = min;
}
result = (rand() % (high - low)) + low;
return (result);
}
Beware! There are many different solutions to this problem and they all have one or another downside. If I was to quickly implement it, I would go for something like this (without too much C-magic going on):
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define SIZE (30)
#define RAND_MIN (1)
#define RAND_MAX (50)
static int randNums(int min, int max) {
// ...
}
int main(void) {
(void) srand(time(NULL));
int arr[SIZE];
int used = 0;
while (used < SIZE) {
int num = randNums(RAND_MIN, RAND_MAX);
bool exists = false;
for (int i = 0; i < used; ++i) {
if (arr[i] == num)
exists = true;
}
if (exists == false)
arr[used++] = num;
}
for (int i = 0; i < SIZE; ++i)
(void) printf("%d\n", arr[i]);
return EXIT_SUCCESS;
}
I hope it helps a bit :)
Like this answer, you can do rejection sampling, but the uniform distribution of a fixed number of samples is perfect for a very simple hash set. (Though the asymptotic runtime might be irrelevant for n=6.)
#include <stdlib.h> /* (s)rand */
#include <stdio.h> /* printf */
#include <time.h> /* clock */
#include <assert.h> /* assert */
/* Double-pointers are confusing. */
struct Reference { int *ref; };
/* Simple fixed hash set. */
static struct Reference bins[256];
static int nums[6];
static const size_t no_bins = sizeof bins / sizeof *bins,
no_nums = sizeof nums / sizeof *nums;
static size_t count_num;
/* Uniformly distributed numbers are great for hashing, but possibly clump
together under linear probing. */
static size_t hash(const int n) { return ((size_t)n * 21) % no_bins; }
/* Linear probing. */
static struct Reference *probe(const int n) {
size_t bin_index;
struct Reference *bin;
assert(sizeof bins > sizeof nums);
for(bin_index = hash(n); bin = bins + bin_index,
bin->ref && *bin->ref != n; bin_index = (bin_index + 1) % no_bins);
return bin;
}
/* Return whether it's a new value. */
static int put_in_set(const int n) {
struct Reference *bin = probe(n);
int *num;
assert(count_num < no_nums);
if(bin->ref) return 0; /* Already in hash. */
num = nums + count_num++;
*num = n;
bin->ref = num;
return 1;
}
/* http://c-faq.com/lib/randrange.html */
static int rand_range(const unsigned n) {
unsigned int x = (RAND_MAX + 1u) / n;
unsigned int y = x * n;
unsigned int r;
assert(n > 0);
do {
r = rand();
} while(r >= y);
return r / x;
}
/* Generates random numbers between the inputed max and min without
repetition; [min, max] inclusive. */
static int unique_uniform(const int min, const int max) {
int n;
assert(min <= max && (size_t)(max - min) >= count_num);
do { n = rand_range(max - min + 1) + min; } while(!put_in_set(n));
return n;
}
int main(void) {
int n = 6;
srand((int)clock()), rand(); /* My computer always picks the same first? */
while(n--) { printf("%d\n", unique_uniform(1, 50)); }
return EXIT_SUCCESS;
}
However, if the numbers are densely packed, (eg, unique_uniform(1, 6),) it's going to reject a lot of numbers. Another solution is to take a Poisson distributed numbers as a running sum, (recurrence T(n+1)=T(n)+\mu_{n+1},) where the expected value is the range of numbers divided by the total samples, then take a random permutation.
The code runs just fine but instead of using "for loop" to iterate upto 200000 , I think there can be a better alternative and I am having trouble finding it. I need help to optimise this solution.The time taken by this solution currently is 56ms.
#include <stdio.h>
#include <math.h>
#include <stdbool.h>
int isPrime(long long int number)
{
int i;
for (i=2; i*i<=number; i++) {
if (number % i == 0) return 0;
}
return 1;
}
int returnNPrime(int N)
{
int counter = 0;
int i ;
if(N == 1) return 2;
for(i=3;i<200000;i+=2)
{
if(isPrime(i))
{
counter++;
if(counter == (N-1))
return i;
}
}
return 0;
}
int main(int argc, char *argv[])
{
printf("%d",returnNPrime(10001));
return 0;
}
Don't put an arbitrary stop condition. You know that the list of primes is infinite and that the loop will eventually stop. Write it like this:
int returnNPrime (int N)
{
int counter = 0;
int i;
if (N == 1) return 2;
for (i = 3; ; i += 2)
{
if (isPrime(i))
{
counter++;
if (counter == (N - 1))
return i;
}
}
}
That being said, this solution is inefficient because you don't store previously found primes.
Try something like this:
#include <stdio.h>
#include <stdbool.h>
#define N 10001
int primes[N] = { 2, 3 };
int main ()
{
for (int n = 2; n < N; n++) {
for (int x = primes[n - 1] + 2; ; x += 2) {
bool prime = true;
for (int i = 0; i < n; i++) {
int p = primes[i];
if (p * p > x) {
break;
}
if (x % p == 0) {
prime = false;
break;
}
}
if (prime) {
primes[n] = x;
break;
}
}
}
printf ("%d\n", primes[N - 1]);
}
Read this paper http://cr.yp.to/bib/1996/deleglise.pdf which describes how to count the number of primes <= N in O (n^(2/3)) or so and implement the algorithm. It's substantially faster than the Eratosthenes sieve, because it doesn't actually find any primes but just counts how many there are.
Make an educated guess how large the n-th prime would be. Say the guess is x. Use the algorithm above to find out how many primes <= x there are, then use a sieve if you are close enough, or use a better guess with the information you just found and try again. Total time O (n^(2/3)).
With some decent hardware and a lot of patience this will let you find solutions up to n = 10^22 or so.
OP's method consumes a lot of time with as it does not take advantage that there is no need to determine the remainder if i is not a prime.
for (i=2; i*i<=number; i++) {
if (number % i == 0) return 0;
The Sieve_of_Eratosthenes is likely faster yet is a dramatic change from OP's code.
Suspect this code is still too slow for OP.
The follows adjust OP's code by only attempting to test against previously found primes. Also it uses pcandidate / plist[index] as part of a terminating condition. Optimized compilers often can provide this at a small cost once pcandidate % plist[index] is computed.
bool prime_test(const unsigned long *plist, unsigned long long pcandidate) {
if (pcandidate <= 2) return pcandidate == 2;
for (size_t index = 0; ; index++) {
unsigned long long remainder = pcandidate % plist[index];
if (remainder == 0) return false;
unsigned long long quotient = pcandidate / plist[index];
if (quotient < plist[index]) return true;
}
assert(0);
return true;
}
unsigned long long prime_nth(size_t n) {
unsigned long plist[n+1];
plist[0] = 2;
unsigned long long pcandidate = plist[0];
for (size_t index = 0; index <= n; index++) {
while (!prime_test(plist, pcandidate)) pcandidate++;
plist[index] = (unsigned long) pcandidate;
pcandidate++;
}
return plist[n];
}
A classic simplification involves only seeking new primes amongst odd numbers. Also change all math to unsigned. Left for OP.
So here is my code . I am trying to find a short way to make this programme work withouth changing any of the arregment.I have been tought the buble way i think its called to arrange a group from highest to lowest but it clearly say in my given orders not to change the entire group.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int randomInRange (unsigned int min, unsigned int max)
{
//srand(time(NULL));
int base_random = rand();
if (RAND_MAX == base_random) return randomInRange(min, max);
int range = max + 1 - min,
remainder = RAND_MAX % range,
bucket = RAND_MAX / range;
if (base_random < RAND_MAX - remainder) {
return min + base_random/bucket;
} else {
return randomInRange (min, max);
}
}
int main()
{
int ari,i,min,max;
printf("Gi'me length of the group")
scanf("%d",&ari);
int pinakas[ari];
printf("Gi'me lowest and highest values");
scanf("%d",&min);
scanf("%d",&max);
for(i = 0; i < ari; i++)
{
pinakas[ari] = randomInRange(min,max);
}
int el,meg,c;
el = max+1;
meg = min-1;
c = 0;
printf("Highest Lowest");
while( c != 4;)
{
for(i = 0; i < ari; i++)
{
if(el > pinakas[ari])
{
el = pinakas[ari];
}
if( meg < pinakas[ari])
{
meg = pinakas[ari];
}
if(i == 4)
{
printf("%d %d",el,meg);
( is there something that i can put here is order to make el,meg to go for the second lowest ,second highest? and so on till i get the 5 highest and 5 lowests.Keep in mind the the lowest length of my group will be pinakas[5].)
}
}
c++;
}
For each item in the array, up to 5 comparisons are done for the min list and 5 for the max list.
Suggest calling a function to do this in a tidy fashion.
#include<assert.h>
// `list` is `const` as OP says "withouth changing any of the arregment".
void sort_ends(const int *list, size_t listlen, int *minlist, int *maxlist,
size_t mlen) {
assert(list);
assert(minlist);
assert(maxlist);
assert(mlen >= 1);
assert(listlen >= mlen);
minlist[0] = list[0];
// For each element after the first ...
for (size_t i = 1; i < listlen; i++) {
int mincandidate = list[i];
size_t mini = i;
if (mini > mlen) mini = mlen;
do {
mini--;
if (mincandidate >= minlist[mini])
break;
// swap mincandidate and minlist[mini]
int t = mincandidate;
mincandidate = minlist[mini];
minlist[mini] = t;
} while (mini > 0);
}
// Do similar for maxlist, left for OP
}
int main() {
int ari;
// ...
int pinakas[ari];
// ...
int mlen = 5;
int minlist[mlen];
int maxlist[mlen];
sort_ends(pinakas, ari, minlist, maxlist, mlen);
return 0;
}
Alternative approach, find min index and then memove().