C - Middle Square Random Number Generator - c

So, I tried to implement the Middle Square PRNG method, to generate the first 100 numbers. It works well until a certain point, when I get as a result negative numbers.
I used the time library to change the values on my temp array, so that it won't get stuck on the same sequence, where the number ends with two zeros.
My code :
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
time_t now;
struct tm *tm;
unsigned long int prng(int seed)
{
int num = seed * seed;
int t[10], inc = 0;
//Reverse number in an array
while(num != 0)
{
t[inc] = num%10;
num /= 10;
inc++;
}
int min = inc/4;
int max = inc / 2 + min;
int temp[10];
//Assign the middle square part to another table
for(int i = min; i <= max; i++)
{
temp[i-min] = t[i];
}
for(int i=0; i < max-min; i++)
{
//Check if there is a "0" "0" sequence, if TRUE - replace with current time (seconds)
if(temp[i] == 0 && temp[i+1] == 0)
{
now = time(0);
tm = localtime(&now);
temp[i] = tm->tm_sec/10;
temp[i + 1] = tm->tm_sec%10;
}
}
//Transform the squared array into an integer
unsigned long int k = 0;
for (int i = 0; i <= max-min; i++)
k = 10 * k + temp[i];
return k;
}
int main()
{
unsigned long int n = 123; //seed
printf("%d ", n);
for(int i = 0; i<100; i++)
{
n = prng(n);
printf("\n%d ", n);
}
return 0;
}
The results that I get:
123
215
226
701
419
6557
24992
7064
7099
85930
-696950
8997
6490
10212
94824
36561
760763
-724206
30238
66334
22325
65048
-94273
...

Related

C segmentation fault threads

This is a program made in C that compiles fine using gcc filename.c -o file -pthread. However when I go to run the program is tells me there is a segmentation fault and I am not sure how to fix it. This program is meant to make random integers in an array then compare how long it takes to find the 10 largest and 10 lowest numbers using a different amount of threads for reach iteration of the program.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <time.h>
#define arraySize 10000
#define lval 0
#define hval 50000
#define maxthread 100
int num[arraySize];
int maxs[maxthread];
int mins[maxthread];
int threadsize;
int threadnum = 0;
void fill(){
int i;
int tmp[hval];
for(i = lval;i < hval;i++)tmp[i] = i;
for(i = 0;i < arraySize;i++){
int t= i + rand()%(hval - 1);
int temp = tmp[i];
tmp[i] = tmp[t];
tmp[t] = temp;
num[i] = tmp[i];
}
}
void print(){
int i;
printf("First 10 Numbers are: \n");
for(i = 0;i < 10;i++)printf("\t%d\n",num[i]);
printf("\n\nLast 10 Numbers: \n");
for(i = (arraySize - 10);i < arraySize;i++)printf("\t%d\n",num[i]);
}
void *getminmax(void *arg){
int i,n = threadnum++;
int max = lval,min = hval;
for(i = n*(arraySize / threadsize);i < (n + 1)*(arraySize / threadsize);i++){
if (num[i] > max)max = num[i];
if (num[i] < min)min = num[i];
}
maxs[n] = max;
mins[n] = min;
printf("Threads:%d Min: %d Max%d Thread Num: %d\n",threadsize,min,max,n);
}
void search(){
int max = lval, min = hval;
int i;
int start = clock();
pthread_t threads[threadsize];
for(i = 0;i < threadsize;i++)
pthread_create(&threads[i],NULL,getminmax,(void*)NULL);
for(i = 0;i < threadsize;i++)
pthread_join(threads[i],NULL);
for(i = 0;i < threadsize;i++){
if(maxs[i] > max)max = maxs[i];
if(mins[i] < min)min = mins[i];
}
int end = clock();
int d = end - start;
printf("Threads %d Min: %d Time Taken: %d \n\n",threadsize,min,max,d);
}
int main(){
fill();
print();
threadsize = 2;
threadnum = 0;
search();
threadsize = 10;
threadnum = 0;
search();
threadsize = 100;
threadnum = 0;
search();
return 0;
}
There are few obvious bugs in your program.
As yano pointed out, t = i + rand()%(hval - 1); will produce a t in the range between 0 and arraySize + hval - 2. That later value is well outside the valid range for accessing tmp[t] and is likely the cause of the segmentation fault.
You probably meant this instead: t = (i + rand()) % (hval - 1);
The construct below is a data race. You are not at all guaranteeing distinct ns for different threads.
int n = threadnum++;
The usual fix for problem 2 is to pass the thread number as the arg (which you didn't use).

for loop unexpectedly jumping down in value

Goldbach's conjecture states that every even integer over 4 is the sum of two primes, I am writing a program in C to find these pairs. To do this it first finds all the primes less than a user given number. I have a for loop to iterate from 4 to the user given number and find the pairs within the loop body. When that loop gets to about around 40, suddenly jumps back down by about 30 and then continues to iterate up (with user input 50 it jumped from 38 to 9, with input 60 it jumped from 42 to 7). I can't figure out why this is happening. Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <sys/types.h>
#include <unistd.h>
struct pair{
int a;
int b;
}pair_t;
int main(){
int N;
int numPrimes = 1;
int *primes = malloc(100*sizeof(int));
int isPrime = 1;
primes[0] = 2;
int timesRealloc = 0;
int availableSlots = 100;
printf("Please enter the largest even number you want to find the Goldbach pair for: \n");
scanf("%d", &N);
struct pair pairs[N/2 + 4];
int j = 0;
int i;
for (i = 3; i <= N; i+=2){
j = 0;
isPrime = 1;
while (primes[j] <= sqrt(i)) {
if (i%primes[j] == 0) {
isPrime = 0;
break;
}
j++;
}
if (isPrime == 1){
primes[numPrimes] = i;
numPrimes++;
}
if (availableSlots == numPrimes){
timesRealloc++;
availableSlots += 100;
primes = realloc(primes, availableSlots*sizeof(int));
}
}
printf("The largest prime I found was %d\n", primes[(numPrimes-1)]);
int k;
for (i=4; i<=N; i+=2){
printf("i is %d, N is %d\n", i, N);
if (i > N){ break; }
for (j=0; j<numPrimes; j++){
for (k=0; k<numPrimes; k++){
int sum = primes[j] + primes[k];
if(sum == i){
pairs[i].a = primes[j];
pairs[i].b = primes[k];
}
}
}
}
for (i=4; i<=N; i+=2){
printf("%d is the sum of %d and %d\n", i, pairs[i].a, pairs[i].b);
}
return 0;
}
You attempt to be space efficient by compressing the pairs array to just hold every other (even) number and start from 4 instead of zero. However, you miscalculate its size and then when you go to use it, you treat it like it hasn't been compressed and that there's a slot for every natural number.
The code suffers from having the prime array calculation in main() along with the other code, this is best separated out. And when it looks for pairs, it doesn't quit when it finds one, nor when it starts getting sums greater than the target. My rework below attempts to address all of these issues:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <stdbool.h>
#define INITIAL_SLOTS (100)
struct pair {
int a;
int b;
} pair_t;
int compute_primes(int limit, unsigned **primes, int size) {
int numPrimes = 0;
(*primes)[numPrimes++] = 2;
for (int i = 3; i <= limit; i += 2) {
bool isPrime = true;
for (int j = 0; (*primes)[j] <= i / (*primes)[j]; j++) {
if (i % (*primes)[j] == 0) {
isPrime = false;
break;
}
}
if (isPrime) {
(*primes)[numPrimes++] = i;
}
if (numPrimes == size) {
size *= 2;
*primes = realloc(*primes, size * sizeof(unsigned));
}
}
return numPrimes;
}
int main() {
int N;
printf("Please enter the largest even number you want to find the Goldbach pair for: \n");
scanf("%d", &N);
unsigned *primes = calloc(INITIAL_SLOTS, sizeof(unsigned));
int numPrimes = compute_primes(N, &primes, INITIAL_SLOTS);
printf("The largest prime I found was %d\n", primes[numPrimes - 1]);
struct pair pairs[(N - 4) / 2 + 1]; // compressed data structure
for (int i = 4; i <= N; i += 2) {
int offset = (i - 4) / 2; // compressed index
bool found = false;
for (int j = 0; ! found && j < numPrimes; j++) {
for (int k = 0; ! found && k < numPrimes; k++) {
int sum = primes[j] + primes[k];
if (sum == i) {
pairs[offset].a = primes[j];
pairs[offset].b = primes[k];
found = true;
} else if (sum > i) {
break;
}
}
}
}
for (int i = 4; i <= N; i += 2) {
int offset = (i - 4) / 2; // compressed index
printf("%d is the sum of %d and %d\n", i, pairs[offset].a, pairs[offset].b);
}
free(primes);
return 0;
}
OUTPUT
> ./a.out
Please enter the largest even number you want to find the Goldbach pair for:
10000
The largest prime I found was 9973
4 is the sum of 2 and 2
6 is the sum of 3 and 3
8 is the sum of 3 and 5
10 is the sum of 3 and 7
12 is the sum of 5 and 7
14 is the sum of 3 and 11
...
9990 is the sum of 17 and 9973
9992 is the sum of 19 and 9973
9994 is the sum of 53 and 9941
9996 is the sum of 23 and 9973
9998 is the sum of 31 and 9967
10000 is the sum of 59 and 9941
>

Adding two numbers [1, 10^10000] as arrays of chars - C

I tackled the problem by first figuring out the length of two given numbers and aligning the one with less digits (if one exists) into a new array so that the ones, tens, hundreds etc. align with the bigger number's ones, tens, hundreds, etc.
Then I wanted to save the sum of each two aligned elements (with a mod of 10) into a new array while checking if the sum of digits is greater than 10 - just the basic sum stuff. Now the problem occurs with adding two elements into the aplusb integer and I've tried fixing it with writing
int aplusb = (lengthA[max-i]-'0') +(temp[max-i]-'0');
but it doesn't work. I'm stuck and I don't know what to do. Please help.
The whole code:
#include <stdio.h>
#include <math.h>
int main(){
char a[10000];
char b[10000];
scanf("%s %s", &a, &b);
char sum[10000];
int lengthA = 0;
int lengthB = 0;
int i = 0;
while(a[i]){
i++;
} lengthA = i;
i = 0;
while(b[i]){
i++;
} lengthB = i;
char temp[10000];
int aplusb;
int carry = 0;
int max = lengthA;
int difference = abs(lengthA - lengthB);
if(lengthA>lengthB){
for(i=0; i<lengthA; i++){
temp[i+difference]=b[i];
}
for(i=0; i<=max; i++){
aplusb = lengthA[max-i]+temp[max-i]; //<-- this is the problematic line
if(carry = 1) aplusb++;
if(aplusb>9){
carry = 1;
aplusb%=10;
}
sum[i]=aplusb;
}
}
for(i=0; i<=max; i++){
printf("%c", sum[i]);
}
/*
if(lengthB>lengthA){
max = lengthB;
for(i=0; i<lengthB; i++){
temp[i+difference]=a[i];
}
}*/
return 0;
}
Doing operations and storing on very large numbers is very akin to doing operations and storing polynomials, i.e. with x = 10. a0 + a1.10 + a2.10^2 ... + an.10^n.
There are many polynomial libraries on the Internet, where you could find inspiration. All operations on your very large numbers can be expressed in terms of polynomials. This means that by using base 2^8, or even base 2^63, instead of base 10 to internally store your large numbers you would greatly improve performance.
You must also normalize your coefficients after operations to keep them positive. Operations may result in a negative coefficient, That can easily be fixed, as it is very similar to borrowing after a subtraction, this means coefficients must be larger than your base by 1bit.
To convert back to base 10, you'd need to solve r (your result) for v (your value), such as r(10)=v(2^63). This has only one solution, if you enforce the positive coefficients rule.
[note] After thinking about it some more: the rule on positive coefficients may only be necessary for printing, after all.
Example: adding. no memory error checking
int addPolys(signed char** result, int na, const signed char* a, int nb, const signed char* b)
{
int i, nr, nmin, carry, *r;
nr = max(na, nb) + 1;
nmin = min(na, nb);
r = malloc(sizeof(signed char) * (na + nb + 1));
if (nb < na)
{
nr = nb;
}
for (i = 0; i < nmin; ++i)
{
r[i] = a[i] + b[i];
}
for (; i < na; ++i)
{
r[i] = a[i];
}
for (; i < nb; ++i)
{
r[i] = b[i];
}
r[nr - 1] = 0;
// carry - should really be a proc of its own, unoptimized
carry = 0;
for (i = 0; i < nr; ++i)
{
r[i] += carry;
if (r[i] > 10)
{
carry = r[i] / 10;
r[i] %= 10;
}
else if (r[i] < 0)
{
carry = (r[i] / 10) - 1;
r[i] -= (carry * 10);
}
else
carry = 0;
}
// 'remove' leading zeroes
for (i = nr - 1; i > 0; --i)
{
if (r[i] != 0) break;
}
++i;
*result = r;
if (i != nr)
{
*result = realloc(i * sizeof(signed char));
}
return i; // return number of digits (0 being 1 digit long)
}
That code is working now for any two positive numbers with up to ten thousand digits:
#include <stdio.h>
#include <math.h>
#include <string.h>
int main(){
char chara[10000];
char charb[10000];
scanf("%s %s", &chara, &charb);
int lengthA = strlen(chara);
int lengthB = strlen(charb);
int max = lengthA;
if(lengthB>lengthA) max=lengthB;
int dif = abs(lengthA - lengthB);
//ustvari int tabele
int a[max];
int b[max];
int sum[max+1];
// nastavi nule
int i;
for(i=0; i<max; i++){
a[i] = 0;
b[i] = 0;
sum[i] = 0;
} sum[max] = 0;
//prekopiraj stevila iz char v int tabele &obrni vrstni red
for(i=0; i<lengthA; i++){
a[i] = chara[lengthA-i-1]-'0';
}
for(i=0; i<lengthB; i++){
b[i] = charb[lengthB-i-1]-'0';
}
int vsota;
int prenos = 0;
for(i=0; i<max; i++){
vsota = a[i]+b[i] + prenos;
if(vsota>=10) prenos = 1;
else if (vsota<10) prenos = 0;
sum[i]=vsota%10;
}
if(prenos==1){
sum[max] = 1;
for(i = max; i>=0; i--){
printf("%d", sum[i]);
}
} else {
for(i = max-1; i>=0; i--){
printf("%d", sum[i]);
}
}
return 0;
}

A simple program for splitting numbers does not display zeroes

I wrote a simple program in c that accepts two numbers and then splits the first number considering the digits of the second number like this:
Input:
362903157 2313
Output:
36
290
3
157
Everything works just fine, except when there are zeroes in the first number, my program skips them. For instance the upper example gives me this output:
36 293 1 570
And that is mycode:
#include <stdio.h>
int nDigits(unsigned i) {
int n = 1;
while (i > 9) {
n++;
i /= 10;
}
return n;
}
// find the highest multiple of 10
int multipleOfTen(int num){
int multiple = 1;
while(multiple <= num){
multiple *= 10;
if(multiple > num){
multiple /= 10;
break;
}
}
return multiple;
}
int main(){
int n, m, digit;
scanf("%d %d", &n, &m);
int lengthOfM = nDigits(m);
for (int i = 0; i < lengthOfM; i++){
digit = m / multipleOfTen(m); //2
for(int j = 1; j <= digit; j++){
printf("%d", n/multipleOfTen(n));
n = n% multipleOfTen(n);
}
printf("\n");
m = m % multipleOfTen(m);
}
return 0;
}
What should I change in my program so that the zeroes won't be ignored?
Instead of calling multipleOfTen() in each loop, call it once and save the result for both n and m. Then in each loop divide those results by 10
#include <stdio.h>
int nDigits(unsigned i) {
int n = 1;
while (i > 9) {
n++;
i /= 10;
}
return n;
}
// find the highest multiple of 10
int multipleOfTen(int num){
int multiple = 1;
while(multiple <= num){
multiple *= 10;
if(multiple > num){
multiple /= 10;
break;
}
}
return multiple;
}
int main(){
int n, m, digit;
int i, j;
int n10, m10;
scanf("%d %d", &n, &m);
int lengthOfM = nDigits(m);
n10 = multipleOfTen(n); //get the multiple of ten once
m10 = multipleOfTen(m);
for ( i = 0; i < lengthOfM; i++){
digit = m / m10;
m10 /= 10;
for( j = 0; j < digit; j++){
printf("%d", n/n10);
n = n% n10;
n10 /= 10;// divide by 10
}
printf("\n");
m = m % multipleOfTen(m);
}
return 0;
}
I suppose an approach like this is inadmissible?
#include <stdio.h>
#include <string.h>
int main ( void ) {
char n[64];
char m[64];
char * p = n;
int i = 0;
int c;
scanf("%63[0-9] %63[0-9]", n, m);
while ((c = m[i++]) != '\0') {
int j = c - '0';
while (j-- > 0) if (*p) putchar(*p++);
putchar(' ');
}
putchar('\n');
return 0;
}
when n=903157 and after n = n% multipleOfTen(n); n becomes 3157 not 03157 so when u dividing again in line printf("%d", n/multipleOfTen(n)); it prints 3 not 0 what you want!!
Fix your code to produce right output.

How to Avoid repeating number randomized in C

int i,j,vec[15]={0};
srand (time(NULL));
for (i=0;i<15;i++){
vec[i]=rand() % 25+1;
for (j=0;j<15;j++){
if (i!=j){
while(vec[i]==vec[j]){
vec[i]=rand() % 25+1;
}
}
}
printf("%d\n",vec[i]);
}
return 0;
}
the code still gives me repeated numbers
EXAMPLE:
24
3
7
20
18
10
12
17
9
7
4
25
13
15
21
I cant figure out what to do with it
You have your loops mixed up. The logic is: Generate a random number until you have found one that isn't in the list.
The way you do it, you generate a new number inside the checking loop. But that doesn't work. Say you're generating the 4th number and find it is equal to the third. Then you generate a new one which might well be equal to any you have already checked against.
You also check uninitialised elements when j > i. Your inner loop should only run up to i.
So:
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
int main()
{
int vec[15] = { 0 };
int i, j;
srand(time(NULL));
for (i = 0; i < 15; i++) {
int okay = 0;
while (!okay) {
vec[i] = rand() % 25 + 1;
okay = 1;
for (j = 0; j < i; j++) {
if (vec[i] == vec[j]) okay = 0;
}
}
printf("%d\n", vec[i]);
}
return 0;
}
That still looks a bit awkward with that okay variable. In my opinion, checking for duplicates should be a separate function:
int contains(int arr[], int n, int x)
{
while (n--) {
if (arr[n] == x) return 1;
}
return 0;
}
int main()
{
// snip ...
for (i = 0; i < 15; i++) {
do {
vec[i] = rand() % 25 + 1;
} while (contains(vec, i, vec[i]));
printf("%d\n", vec[i]);
}
// snip ...
}
In your case the range of possible numbers isn't mich bigger than the number of array elements. You could also create an ordered array {1, 2, 3, ..., 25}, then shuffle it and use only the first 15 elements.
Reset j in the while loop:
for (j=0;j<i;j++){ //Use j<i
if (i!=j){
while(vec[i]==vec[j]){
vec[i]=rand() % 25+1;
j=-1;//-1 because in the next iteration,j will start from 0
}
}
}
Are you actually trying to shuffle the numbers, rather than fill the array with randoms? (It looks like you want an array with numbers from 1 to 25, but in random order.) rand() can give you duplicate numbers (they're random, after all!)
Try this:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
int
main( int argc, char **argv )
{
int i, vec[25];
for (i = 0; i < 25; ++i) vec[i] = i + 1;
/* Shuffle entries */
srand( time( 0 ) );
for (i = 0; i < 1000; ++i) {
int a = rand( ) % 25;
int b = rand( ) % 25;
if (a != b) {
int tmp = vec[a];
vec[a] = vec[b];
vec[b] = tmp;
}
}
/* Print shuffled array */
for (i = 0; i < 25; ++i) printf( "%d: %d\n", i, vec[i] );
return 0;
}
#include<stdio.h>
#include<stdlib.h>
int inArray(int, int, int*);
int main()
{
int i,j,vec[15]={0};
int temp;
srand (time(NULL));
for (i=0;i<15;i++){
temp =rand() % 25+1;
while(inArray(i+1,temp, vec) == 1){
temp = rand() % 25+1;
}
vec[i] = temp;
printf("VECT[%d] \t= %d\n",i,vec[i]);
}
return 0;
}
int inArray(int count, int input, int* array){
int i = 0;
for(i=0; i<count; i++){
if(input == array[i]){
return 1;
}
}
return 0;
}
Gave an output:
VECT[0] = 24
VECT[1] = 19
VECT[2] = 1
VECT[3] = 25
VECT[4] = 22
VECT[5] = 18
VECT[6] = 7
VECT[7] = 8
VECT[8] = 12
VECT[9] = 21
VECT[10] = 11
VECT[11] = 6
VECT[12] = 23
VECT[13] = 20
VECT[14] = 15
The checking was off, you would change and not break allowing it to be changed to a previous value.
You can use an array
int randNumbers[25]; // fill it starting 0 to 25 then
randomize the number in a range between 0 and 25 after swap the number in the randomized index with the last number in your array
randomize 0 to 23
and so on....
int main(int argc, char **argv) {
static const int size = 25;
int numbers[size];
for( int i = 0; i < size; i++ ){
numbers[i] = i;
}
srand (time(NULL));
for( int i = 0; i < size; i++ ){
int rIndex = rand()%(size - i);
int rNum = numbers[rIndex];
numbers[rIndex] = numbers[size-i];
printf("%d ", rNum);
}
return 0;
}
O(n) complexity...

Resources