#include <stdio.h>
#include <time.h>
#include <math.h>
#include <stdlib.h>
#define MAXNUM 2000000000
#define MINNUM 1990000001
#define MAXTRIES 10
unsigned long long b, e, m, result;
int modulo(b, e, m)
{
result = 1;
while(e > 0)
{
if(e % 2 == 1)
{
result = (result * b);
}
b = (b * b) % m;
e = e / 2;
}
return result % m;
}
int isPrime(n)
{
unsigned long long a;
int i;
for(i = 1; i <= 10; i++)
{
a = rand() % (n - 1) + 1;
if(modulo(a, n - 1, n) != 1)
{
return 0;
}
}
return 1;
}
int main()
{
unsigned int prime = 0;
unsigned int flag = 0;
unsigned int tries;
unsigned int start;
long curtime;
unsigned long long p;
curtime = time(NULL);
srand((unsigned int) curtime);
printf("Checking range [1990000001, 2000000000] for prime numbers.\n");
if(MINNUM % 2 == 0)
{
start = MINNUM + 1;
}
else
{
start = MINNUM;
}
printf("Trying Fermat test with seed %ld \n\n",curtime);
prime = 0;
for(tries = 1; tries <= MAXTRIES; tries++)
{
clock_t tic = clock();
for(p = start; p <= MAXNUM; p += 2)
{
if(isPrime(p))
prime++;
}
clock_t toc = clock();
printf("Probabilistic algorithm: Found %ld primes in %f seconds.(tries = %d)\n", prime, (double)(toc - tic) / CLOCKS_PER_SEC,tries);
prime = 0;
}
return 0;
}
So the problem is that the algorithm finds in every try 5000000 prime numbers when it should find around 466646 with some deviation. Which means that in every try it should find a number of primes close to the one mentioned above.
It looks like the main problem is caused by integer overflows in the modulo() function. Specifically, result=(result*b) is going to overflow quite regularly. You need to store these variables in 64-bit unsigned integers, and calculate the modulus of this result every time.
This will work (with a few minor corrections elsewhere):
#include <inttypes.h>
#define MAXNUM 2000000000
#define MINNUM 1990000001
#define MAXTRIES 10
uint64_t modulo(uint64_t b, uint64_t e, uint64_t m){
uint64_t result=1;
while(e>0){
if(e%2==1){
result=(result*b)%m;
}
b=(b*b)%m;
e=e/2;
}
return result%m;
}
Result:
Checking range [1990000001, 2000000000] for prime numbers.
Trying Fermat test with seed 1416322197
Probabilistic algorithm: Found 466646 primes in 5.157485 seconds.(tries=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 need to compute the factorial of a number without using the multiplication operator. Because of this restriction, I directly tried to use repeated addition. It kind of works. However, my program is struggling to get the factorial of larger numbers. Is there a better way to solve the problem?
Here is my code:
void main(){
unsigned long num = 0, ans = 1, temp = 1;
printf("Enter a number: ");
scanf("%lu", &num);
while (temp <= num){
int temp2 = 0, ctr = 0;
while (ctr != temp){
temp2 += ans;
ctr ++;
}
ans = temp2;
temp ++;
}
printf("%lu! is %lu\n", num, ans);
}
You can implement a faster (than repeated addition) multiply function using bit shifts and addition to perform "long multiplication" in binary.
unsigned long long mul_ull(unsigned long long a, unsigned long long b)
{
unsigned long long product = 0;
unsigned int shift = 0;
while (b)
{
if (b & 1)
{
product += a << shift;
}
shift++;
b >>= 1;
}
return product;
}
EDIT: Alternative implementation of the above using single bit shifts and addition:
unsigned long long mul_ull(unsigned long long a, unsigned long long b)
{
unsigned long long product = 0;
while (b)
{
if (b & 1)
{
product += a;
}
a <<= 1;
b >>= 1;
}
return product;
}
In practice, whether or not this is faster than repeated addition depends on any optimizations done by the compiler. An optimizing compiler could analyze the repeated addition and replace it with a multiplication. An optimizing compiler could also analyze the code of the mul_ull function above and replace it with a multiplication, but that may be harder for the optimizer to spot. So in practice, it is perfectly reasonable for the repeated addition algorithm to end up faster than the bit-shift and addition algorithm after optimization!
Also, the above implementations of the mul_ull functions will tend to perform better if the second parameter b is the smaller of the numbers being multiplied when the one of the numbers is much larger than the other (as is typical for a factorial calculation). The execution time is roughly proportional to the log of b (when b is non-zero) but also depends on the number of 1-bits in the binary value of b. So for the factorial calculation, put the old running product in the first parameter a and the new factor in the second parameter b.
A factorial function using the above multiplication function:
unsigned long long factorial(unsigned int n)
{
unsigned long long fac = 1;
unsigned int i;
for (i = 2; i <= n; i++)
{
fac = mul_ull(fac, i);
}
return fac;
}
The above factorial function is likely to produce an incorrect result for n > 20 due to arithmetic overflow. 66 bits are required to represent 21! but unsigned long long is only required to be 64 bits wide (and that is typically the actual width for most implementations).
For large values of n, a big format is needed.
As you cannot use multiplications, it seems logical that you must implement it yourself.
In practice, as only additions are needed, it is not so difficult to implement, if we are not looking for a high efficiency.
A little difficulty anyway : you have to convert the input integer in an array of digits.
As modulo is not allowed I guess, I implemented it with the help of snprintf function.
Result:
100! is 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
Note: this result is provided about instantaneously.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NDIGITS 1000 // maximum number of digits
struct MyBig {
int digits[NDIGITS + 2]; // "+2" to ease overflow control
int degree;
};
void reset (struct MyBig *big) {
big->degree = 0;
for (int i = 0; i <= NDIGITS; ++i) big->digits[i] = 0;
}
void create_with_div (struct MyBig *big, int n) { // not used here
reset (big);
while (n != 0) {
big->digits[big->degree++] = n%10;
n /= 10;
}
if (big->degree != 0) big->degree--;
}
void create (struct MyBig *big, int n) {
const int ND = 21;
char dig[ND];
snprintf (dig, ND, "%d", n);
int length = strlen (dig);
reset (big);
big->degree = length - 1;
for (int i = 0; i < length; i++) {
big->digits[i] = dig[length - 1 - i] - '0';
}
}
void print (struct MyBig *big) {
for (int i = big->degree; i >= 0; --i) {
printf ("%d", big->digits[i]);
}
}
void accumul (struct MyBig *a, struct MyBig *b) {
int carry_out = 0;
for (int i = 0; i <= b->degree; ++i) {
int sum = carry_out + a->digits[i] + b->digits[i];
if (sum >= 10) {
carry_out = 1;
a->digits[i] = sum - 10;
} else {
carry_out = 0;
a->digits[i] = sum;
}
}
int degree = b->degree;
while (carry_out != 0) {
degree++;
int sum = carry_out + a->digits[degree];
carry_out = sum/10;
a->digits[degree] = sum % 10;
}
if (a->degree < degree) a->degree = degree;
if (degree > NDIGITS) {
printf ("OVERFLOW!!\n");
exit (1);
}
}
void copy (struct MyBig *a, struct MyBig *b) {
reset (a);
a->degree = b->degree;
for (int i = 0; i <= a->degree; ++i) {
a->digits[i] = b->digits[i];
}
}
void fact_big (struct MyBig *ans, unsigned int num) {
create (ans, 1);
int temp = 1;
while (temp <= num){
int ctr = 0;
struct MyBig temp2;
reset (&temp2);
while (ctr != temp){
accumul (&temp2, ans);
ctr ++;
}
copy (ans, &temp2);
temp ++;
}
return;
}
unsigned long long int fact (unsigned int num) {
unsigned long long int ans = 1;
int temp = 1;
while (temp <= num){
int ctr = 0;
unsigned long long int temp2 = 0;
while (ctr != temp){
temp2 += ans;
ctr ++;
}
ans = temp2;
temp ++;
}
return ans;
}
void main(){
unsigned long long int ans;
unsigned int num;
printf("Enter a number: ");
scanf("%u", &num);
ans = fact (num);
printf("%u! is %llu\n", num, ans);
struct MyBig fact;
fact_big (&fact, num);
printf("%u! is ", num);
print (&fact);
printf ("\n");
}
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.
I'm trying to work through pset1 in Harvard's CS50 class through edX/ iTunesU and I'm attempting to program Luhn's algorithm. The below code is very incomplete but I wanted to know how to use pow() within a for loop and utilizing i within pow(). Presumably, there is another way to program Luhn's algorithm without using pow(), but exploring this method has brought this question to my attention. Any suggestions?
#include <stdio.h>
#include <cs50.h>
#include <math.h>
int main(void) {
long long c = 1234123412341234;
long long temp_c = c;
long long temp_c_one = c;
long long c_one_x = 0;
int count = 0;
while (temp_c > 0LL) {
temp_c = temp_c / 10LL;
count++;
}
for (int i = 0; i < count; i++) {
c_one_x = (temp_c_one % (pow(10, (i + 1))) / (pow(10, i));
count--;
}
}
You can avoid the use of pow by having a counter which you multiply by 10 every loop iteration.
#include <stdio.h>
#include <cs50.h>
#include <math.h>
int main(void) {
long long c = 1234123412341234;
long long temp_c = c;
long long temp_c_one = c;
long long c_one_x = 0;
long long pwr = 1; // 10^0 = 1
int count = 0;
while (temp_c > 0LL) {
temp_c = temp_c / 10LL;
count++;
}
// TODO: Don't think you should decrement count in this loop
for (int i = 0; i < count; i++) {
c_one_x = (temp_c_one % (pwr * 10)) / pwr;
count--;
pwr *= 10;
}
}
However, I'm not convinced you have produced a good Luhns algorithm implementation, so my suggestion is:
// Better Luhn's algorithm
int luhn( long long cc) {
unsigned long check = 0;
unsigned int digit;
for (int i = 0; cc > 0; i++) {
digit = cc % 10;
// double every second digit
if (i % 2) {
digit *= 2;
digit = (digit >= 10) ? (digit + 1) % 10 : digit;
}
check += digit;
cc = cc/10; // next CC digit.
}
return check;
}
int main (void) {
long long c = 1234123412341234;
print "Result is : %d", luhn(c));
}
There are several fast algorithms to calculate prime numbers up to a given number n. But, what is the fastest implementation to list all the numbers r relatively prime to some number n in C? That is, find all the elements of the multiplicative group with n elements as efficiently as possible in C. In particular, I am interested in the case where n is a primorial.
The n primorial is like the factorial except only prime numbers are multiplied together and all other numbers are ignored. So, for example 12 primorial would be 12#=11*7*5*3*2.
My current implementation is very naive. I hard code the first 3 groups as arrays and use those to create the larger ones. Is there something faster?
#include "stdafx.h"
#include <stdio.h> /* printf, fgets */
#include <stdlib.h> /* atoi */
#include <math.h>
int IsPrime(unsigned int number)
{
if (number <= 1) return 0; // zero and one are not prime
unsigned int i;
unsigned int max=sqrt(number)+.5;
for (i = 2; i<= max; i++)
{
if (number % i == 0) return 0;
}
return 1;
}
unsigned long long primorial( int Primes[], int size)
{
unsigned long long answer = 1;
for (int k = 0;k < size;k++)
{
answer *= Primes[k];
}
return answer;
}
unsigned long long EulerPhi(int Primes[], int size)
{
unsigned long long answer = 1;
for (int k = 0;k < size;k++)
{
answer *= Primes[k]-1;
}
return answer;
}
int gcd( unsigned long long a, unsigned long long b)
{
while (b != 0)
{
a %= b;
a ^= b;
b ^= a;
a ^= b;
}
//Return whethere a is relatively prime to b
if (a > 1)
{
return false;
}
return true;
}
void gen( unsigned long long *Gx, unsigned int primor, int *G3)
{
//Get the magic numbers
register int Blocks = 30; //5 primorial=30.
unsigned long long indexTracker = 0;
//Find elements using G3
for (unsigned long long offset = 0; offset < primor; offset+=Blocks)
{
for (int j = 0; j < 8;j++) //The 8 comes from EulerPhi(2*3*5=30)
{
if (gcd(offset + G3[j], primor))
{
Gx[indexTracker] = offset + G3[j];
indexTracker++;
}
}
}
}
int main(int argc, char **argv)
{
//Hardcoded values
int G1[] = {1};
int G2[] = {1,5};
int G3[] = {1,7,11,13,17,19,23,29};
//Lazy input checking. The world might come to an end
//when unexpected parameters given. Its okey, we will live.
if (argc <= 1) {
printf("Nothing done.");
return 0;
}
//Convert argument to integer
unsigned int N = atoi(argv[1]);
//Known values
if (N <= 2 )
{
printf("{1}");
return 0;
}
else if (N<=4)
{
printf("{1,5}");
return 0;
}
else if (N <=6)
{
printf("{1,7,11,13,17,19,23,29}");
return 0;
}
//Hardcoded for simplicity, also this primorial is ginarmous as it is.
int Primes[50] = {0};
int counter = 0;
//Find all primes less than N.
for (int a = 2; a <= N; a++)
{
if (IsPrime(a))
{
Primes[counter] = a;
printf("\n Prime: : %i \n", a);
counter++;
}
}
//Get the group size
unsigned long long MAXELEMENT = primorial(Primes, counter);
unsigned long long Gsize = EulerPhi(Primes, counter);
printf("\n GSize: %llu \n", Gsize);
printf("\n GSize: %llu \n", Gsize);
//Create the list to hold the values
unsigned long long *GROUP = (unsigned long long *) calloc(Gsize, sizeof(unsigned long long));
//Populate the list
gen( GROUP, MAXELEMENT, G3);
//Print values
printf("{");
for (unsigned long long k = 0; k < Gsize;k++)
{
printf("%llu,", GROUP[k]);
}
printf("}");
return 0;
}
If you are looking for a faster prime number check, here is one that is reasonably fast and eliminates all calls to computationally intensive functions (e.g. sqrt, etc..)
int isprime (int v)
{
int i;
if (v < 0) v = -v; /* insure v non-negative */
if (v < 2 || !((unsigned)v & 1)) /* 0, 1 + even > 2 are not prime */
return 0;
for (i = 2; i * i <= v; i++)
if (v % i == 0)
return 0;
return 1;
}
(note: You can adjust the type as required if you are looking for numbers above the standard int range.)
Give it a try and let me know how it compares to the once you are currently using.