This program does Prime Factorization Of Numbers In C.
#include <stdio.h>
int main(void) {
int number, i, p, n, factors, count;
int numbers[1000000];
int counter = 0;
char text[100000];
for (count = 0; count < 1000000; count++) {
fgets(text, 10000000, stdin);
if (sscanf(text, "%d", &number) == 1) {
if (number == 0)
break;
numbers[count] = number;
} else {
numbers[count] = 0;
}
}
counter = 0;
for (i = 0; i < count; i++) {
if ((numbers[i] < 0) || (numbers[i] == 0)) {
fprintf(stderr, "Error: Wrong Input!\n");
return 100;
break;
}
number = numbers[i];
printf("Prime factorization of nubmer %d is:\n", number);
factors = 0;
for (p = 2; p * p <= number; p += 1 + (p & 1)) {
if (number % p == 0) {
n = 0;
factors++;
do {
number /= p;
n++;
} while (number % p == 0);
if (n == 1) {
printf("%d ", p);
++counter;
} else
printf("%d^%d ", p, n);
++counter;
if (count > 0 && number != 1)
printf("x ");
}
}
if (factors == 0 || number != 1)
printf("%d", number);
printf("\n");
}
return 0;
}
This program works fine for numbers smaller than 108. But my question is, if there is a way to make this program even for numbers like 1012. I know that int would not be enough, but when I tried for example long int, it didn't worked. Also I heard something about malloc, but I keep failing to implement (understand) it.
Factorising large numbers usually needs a more subtle approach than simple trial division. Here is a possible outline method:
Make a list of all the primes up to, say, 25,000.
Use the list to remove all prime factors below 25,000.
If there is a remainder > 1 then check if the remainder is prime with a Miller-Rabin test or similar.
If the remainder is prime, then you have found the last factor.
If the remainder is not prime, then you are going to have to factorise it. That will inevitably be slow I'm afraid.
You can use long long. But probably, the real problem is, that it will take a veeeeerrrryyy long time to do the factorization on numbers, that don't fit in a normal int. E.g. you're trying to factorize a prime number in the range 10^12, then you will have to do about 10^6 divisions.
The thing about malloc won't help you with this problem at all, because even bigger values will take even longer to factorize. So, if you want to know, how malloc works, I suggest opening a separate question for that.
Below is a rework of the code using unsigned long long. (I tossed the file stuff to keep this to a minimal example.) Whether this works for your purpose depends on how your system defines a long long (on my system it's 64 bits). I also redid the output format to be compatible with the Unix dc command's postfix notation so I could easily check if the results were correct:
#include <stdio.h>
#include <stdlib.h>
int main() {
unsigned long long large = 18446744073709551615ULL; // 2^64 - 1
for (unsigned long long counter = large - 1000; counter < large; counter++) {
unsigned long long number = counter;
printf("Prime factorization of %llu is:", number);
unsigned long factors = 0;
for (unsigned long long p = 2; p * p <= number; p += 1 + (p & 1)) {
if (number % p == 0) {
factors++;
unsigned long n = 0;
do {
number /= p;
n++;
} while (number % p == 0);
if (n == 1) {
printf(" %llu", p);
}
else {
printf(" %llu %lu ^", p, n);
}
if (number != 1 && factors > 1) {
printf(" *");
}
}
}
if (factors == 0 || number != 1) {
factors++;
printf(" %llu", number);
}
if (factors > 1) {
printf(" *");
}
printf("\n");
}
return 0;
}
SAMPLE OUTPUT
% ./a.out
Prime factorization of 18446744073709550615 is: 5 563 * 751 * 8725722280871 *
Prime factorization of 18446744073709550616 is: 2 3 ^ 3 * 41 * 7523 * 8243 * 14479 * 20879 *
Prime factorization of 18446744073709550617 is: 79 557 * 419215600611539 *
Prime factorization of 18446744073709550618 is: 2 2298974999 * 4011949691 *
Prime factorization of 18446744073709550619 is: 3 3 ^ 1008659 * 677347590683 *
Prime factorization of 18446744073709550620 is: 2 2 ^ 5 * 7 * 149 * 233 * 3795329598449 *
Prime factorization of 18446744073709550621 is: 11 23 * 72912031911895457 *
Prime factorization of 18446744073709550622 is: 2 3 * 479909 * 6406334004193 *
Prime factorization of 18446744073709550623 is: 3421377637 5391612979 *
Prime factorization of 18446744073709550624 is: 2 5 ^ 61 * 593 * 1699 * 9379762391 *
Prime factorization of 18446744073709550625 is: 3 5 4 ^ * 13 * 756789500459879 *
Prime factorization of 18446744073709550626 is: 2 3743461 * 2463862195133 *
Prime factorization of 18446744073709550627 is: 7 1283 * 4339 * 627089 * 754877 *
Prime factorization of 18446744073709550628 is: 2 2 ^ 3 2 ^ * 101 * 293 * 42751 * 405025111 *
Prime factorization of 18446744073709550629 is: 17 43 * 613 * 66457 * 619442699 *
...
This runs slower but reasonably. You can push this further on some systems by swapping unsigned long long for a uint128_t which some compilers support somewhat:
typedef unsigned __int128 uint128_t;
(And up the unsigned long declarations to unsigned long long.) You'd need to supply number printing routines for the uint128_t type as printf() isn't going to handle them directly. I tried this with the above code and it worked:
Prime factorization of 340282366920938463426481119284349108124 is: 2 2 ^ 31 * 6131 * 7654271 * 21163829 * 21491837 * 128562653437 *
% dc
2 2 ^ 31 * 6131 * 7654271 * 21163829 * 21491837 * 128562653437 * p
340282366920938463426481119284349108124
But I never saw it complete more than one number while running it!
Using type unsigned long long for number and the prime factors will take you to 1019 at the price of longer computation times.
Note however that defining a large local array with automatic storage may cause problems, especially when it reaches a size of 8 megabytes as would be the case for type unsigned long long (this type is at least 64-bit wide). Allocating it from the heap is safer.
Here is an adapted version of the code:
#include <stdio.h>
#include <stdlib.h>
#define NUMBER_MAX 1000000
int main(void) {
unsigned long long *numbers;
unsigned long long number, p;
int i, n, factors, count;
char text[100];
numbers = calloc(NUMBER_MAX, sizeof(*numbers));
if (numbers == NULL) {
printf("cannot allocate number array\n");
return 1;
}
for (count = 0; count < NUMBER_MAX; count++) {
if (!fgets(text, sizeof text, stdin)) {
break;
}
if (sscanf(text, "%llu", &number) == 1 && number > 0) {
numbers[count] = number;
} else {
fprintf(stderr, "Error: Wrong Input!\n");
return 100;
}
}
for (i = 0; i < count; i++) {
number = numbers[i];
printf("Prime factorization of nubmer %llu is:\n", number);
factors = 0;
for (p = 2; p < 0x100000000 && p * p <= number; p += 1 + (p & 1)) {
if (number % p == 0) {
n = 0;
factors++;
do {
number /= p;
n++;
} while (number % p == 0);
if (n == 1) {
printf("%llu ", p);
} else {
printf("%llu^%d ", p, n);
}
if (number != 1) {
printf("* ");
}
}
}
if (factors == 0 || number != 1) {
printf("%llu", number);
}
printf("\n");
}
free(numbers);
return 0;
}
Related
I've come up with a very efficient algorithm for calculating prime numbers. It uses bit arithmetics ie AND , OR, XOR etc. and its based on the sieve of eratosthenes.
For numbers below 32 it works. For example when n = 31 I get the output:
2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31,
But when I use a bigger value such as 40 I get a different output:
2,
I am at a loss to explain why this is so, I need guidance.
Below is the code:
https://github.com/rsgilbert/c/blob/master/chp2/sieve-bitset.c
#include <stdio.h>
#include <math.h>
#define MAXLINE 1000
#define A_1 1 // first number in GP
// sieve of eratosthenes
// Using bit arithmetic
long btoi(char s[]);
void itob(long n, char s[]);
long runningPrimes(long max);
void printBits(long num);
long gpSum(long a_1, long r, long n);
long numElementsInGP(long a_1, long a_n, long r);
long lastElementInBitset(long width);
long width(long factor, long n);
long paddedSum(long sum, long n, long i);
long commonRatio(long i);
long flip(long bitset);
void sieve(long n, long primes[]);
long dropRightBits(long bitset, long noToDrop);
void primeBitsetToArray(long bitset, long primes[]);
void printPrimes(long primes[], size_t size);
long greaterFirstBit(long bitset);
long main()
{
long n = 31; // 32 is not supported (??) I dont know why
long runner = runningPrimes(n);
long primes[n];
sieve(n, primes);
printPrimes(primes, n);
}
/**
* sieve of eratosthenes
* Algorithm for finding all prime numbers upto a given limit.
* We go through natural numbers starting with 2 removing out multiples of each.
*/
void sieve(long n, long primes[])
{
// 1. fill in numbers
long runner = runningPrimes(n);
long start_no = 2;
long i = start_no;
while(i <= n)
{
// printf("%d\n", i);
long w = width(i, n);
long lastEl = lastElementInBitset(w);
long r = commonRatio(i);
long numEls = numElementsInGP(A_1, lastEl, r);
long sum = gpSum(A_1, r, numEls);
// printf("non padded sum: w %d , r %d , numEls %d ", w, r, numEls);
// printBits(sum);
sum = paddedSum(sum, n, i);
// We need to flip `sum` bits because currently 1s in sum represent multiples
// If we flip 1010 it becomes 101. But notice we also want to remove 1000.
// If we dont handle this, 4 will show up in the primes
// So we first get a copy of first bit
long grtrBitset = greaterFirstBit(sum);
sum = flip(sum);
sum = grtrBitset | sum;
//
// printf("sum: gr %d ", grtrBitset);
// printBits(grtrBitset);
// printf("sum ");
// printBits(sum);
// Cancel out bits that represent multiples of i
// We are going to drop some bits. The ones that are multiples of i
// We first store some values
long bitsOnRightToDrop = n - (2 * i) + 1;
long notToChangeBits = dropRightBits(runner, bitsOnRightToDrop);
long withoutSum = runner & sum;
// printf("Runner: ");
runner = notToChangeBits | withoutSum;
// printBits(runner);
i++;
}
primeBitsetToArray(runner, primes);
}
long runningPrimes(long max)
{
return pow(2, max) - 1;
}
long paddedSum(long sum, long n, long i) {
return sum * pow(2, (n % i));
}
/** Find sum of a geometric progression
* a_1: first element in GP
* r: common ratio
* n: number of elements in GP
*/
long gpSum(long a_1, long r, long n)
{
return a_1 * (pow(r, n) - 1) / (r - 1);
}
/* Compute common ratio to be used for a given number */
long commonRatio(long i)
{
return pow(2, i);
}
/** Find number of elements in a GP
* a_1: first element in GP
* a_n: last element in GP
* r : common ratio
*/
long numElementsInGP(long a_1, long a_n, long r)
{
return log2(a_n / a_1) / log2(r) + 1;
}
/* Find last element in bitset as decimal integer
* For example if bitset is 10010 , last element is 10000 = 16
* width: Number of characters in bitset.
*/
long lastElementInBitset(long width)
{
return pow(2, (width - 1));
}
/* Produces the number of bits from first multiple greater than factor to last multiple less than n. */
long width(long factor, long n)
{
long firstMultGR = 2 * factor;
long lastMultLess = n - (n % factor);
return lastMultLess - firstMultGR + 1;
}
// -- Bit functions --
/** Convert binary to decimal integer */
long btoi(char s[])
{
long result = 0;
long i = 0;
while (s[i] != 0)
{
if (s[i] != '0' && s[i] != '1')
return -1;
result *= 2;
result += s[i] - '0';
i++;
}
return result;
}
/** convert decimal integer to binary */
void itob(long n, char s[])
{
if (n == 0)
{
s[0] = '0';
s[1] = 0;
return;
};
if (n < 0)
{
s[0] = '-';
s[1] = '1';
s[2] = 0;
return;
}
long pos = log2(n);
s[pos + 1] = 0;
while (pos != 0)
{
s[pos] = '0' + n % 2;
n = n / 2;
pos--;
}
// pos will be 0
s[pos] = '1';
}
/**
* Prints binary representation of set
*/
void printBits(long num)
{
char result[MAXLINE];
itob(num, result);
printf("%s\n", result);
}
// Flip bits. For example 10110 becomes 1001
long flip(long bitset)
{
long mask = pow(2, (long) log2(bitset) + 1) - 1;
return bitset ^ mask;
}
// Drop some bits from the right side of a bitset. For example dropRighBits(btoi("1001100110"), 6) produces 1001000000
long dropRightBits(long bitset, long noToDrop) {
long mask = pow(2, noToDrop) - 1;
long rightFlippedBitset = bitset ^ mask;
return bitset & rightFlippedBitset;
}
/* Copy bitset representing prime positions into an array of prime numbers */
void primeBitsetToArray(long bitset, long primes[])
{
char temp[MAXLINE];
itob(bitset, temp);
// printf("bitset %s\n", temp);
// in the bitset, the first position represents number 1 then 2 ... etc So our primes will start at index 1
long i = 1;
long j = 0;
while(temp[i] != 0)
{
if(temp[i] == '1')
{
// in the bitset, the first position is 1 then 2 ... etc
primes[j] = i + 1;
// printf("%d\n", i + 1);
j++;
}
i++;
}
primes[j] = -1;
}
/* Return bitset for the first bit in a given bitset.
* For example bitsetForFirstBit(10) = 8
*/
long bitsetForFirstBit(long bitset) {
return pow(2, log2(bitset));
}
/* Return bitset that is greater than given bitset but also a multiple of 2.
* For example bitsetForFirstBit(10) = 16
*/
long greaterFirstBit(long bitset) {
return pow(2, (long) log2(bitset) + 1);
}
void printPrimes(long primes[], size_t size)
{
long i = 0;
while(i < size && primes[i] != -1)
{
printf("%d, ", primes[i]);
i++;
}
printf("\n");
}
I wrote this code to find the prime factorization of a number. I just cannot figure out the last part. If x is entered as a double or float, the program should print an error message and terminate. How do I achieve this?
#include <stdio.h>
int main()
{
int x, i;
printf("Enter an integer: ");
scanf("%d", &x);
if (x <= 1)
{
return 1;
}
printf("The prime factorization of %d is ", x);
if (x > 1)
{
while (x % 2 == 0)
{
printf("2 ");
x = x / 2;
}
for (i = 3; i < 1009; i = i + 2)
{
while (x % i == 0)
{
printf("%d ", i);
x = x / i;
}
}
}
return 0;
}
Your starting point should cover all desired and undesired cases so you should take float number from a user, not int. Then, you should check whether whole decimal part of the number is 0. That is, if all of them equals 0, the user want to provide an int number instead of float.
First step is to declare a float number:
float y;
After, take its value from the user:
scanf("%f", &y);
Second step is to check whether it is int or float. There are many ways for this step. For example, I find roundf() function useful. It takes a float number and computes the nearest integer to this number. So if the nearest integer is the number itself then the number has to be int. Right?
if(roundf(y)!=y)
If you are sure it is an int, you can move onto the third step: convert float type to int type. It is called type-casting. This step is required for the remaining part of your program because in your algorithm you manipulate the number with int type so just convert it to int:
x = (int)y;
After adding the line above, you can use the rest of code which you typed. I give the whole program:
#include <stdio.h>
#include <math.h>
int main()
{
int x,i;
float y;
printf("Enter an integer: ");
scanf("%f", &y);
if(roundf(y)!=y){
printf("%f is not an integer!",y);
return 1;
}
else{
x = (int)y;
}
if (x <= 1)
{
printf("%d <= 1",x);
return 1;
}
else
{
printf("The prime factorization of %d is ", x);
while (x%2 == 0)
{
printf("2 ");
x = x / 2;
}
for ( i = 3; i < 1009; i = i + 2)
{
while (x%i == 0)
{
printf("%d ",i);
x = x / i;
}
}
}
return 0;
}
The use of scanf() is a bit tricky, I would avoid it to scan user generated input at almost all cost. But nevertheless here is a short overview for how to get the errors of scanf()
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
int main(void)
{
int x, i, scanf_return;
printf("Enter an integer: ");
/* Reset "errno". Not necessary here, just in case. */
errno = 0;
/* scanf() returns a value in case of an error */
scanf_return = scanf("%d", &x);
/*
* scanf() returns "EOF" if it didn't find all what you wanted or
* and error happened.
* It sets "errno" to the value of the actual error. See manpage
* for all of the details.
*/
if (scanf_return == EOF) {
/*
* The error is connected to the stream, so we can differ between
* an error within scanf() and and error with the input stream
* (here: stdin)
*/
if (ferror(stdin)) {
fprintf(stderr, "Something went wrong while reading stdin: %s\n", strerror(errno));
exit(EXIT_FAILURE);
} else {
/* e.g. a conversion error, a float instead of an integer, letters
instead of a decimal number */
fprintf(stderr, "Something went wrong within scanf()\n");
exit(EXIT_FAILURE);
}
}
/*
* If no error occurred, the return holds the number of objects
* scanf() was able to read. We only need one, but it would throw an
* error if cannot find any objects, so the check is here for
* pedagogical reasons only.
*/
if (scanf_return != 1) {
fprintf(stderr, "Something went wrong within scanf(): wrong number of objects read.\n");
exit(EXIT_FAILURE);
}
if (x <= 1) {
fprintf(stderr, "Input must be larger than 1!\n");
exit(EXIT_FAILURE);
}
printf("The prime factorization of %d is ", x);
/* No need for that test, x is already larger than one at this point. */
/* if (x > 1) { */
while (x%2 == 0) {
printf("2 ");
x = x / 2;
}
for (i = 3; i < 1009; i = i + 2) {
while (x%i == 0) {
printf("%d ",i);
x = x / i;
}
}
/* } */
/* Make it pretty. */
putchar('\n');
exit(EXIT_SUCCESS);
}
Does it work?
$ ./stackoverflow_003
Enter an integer: 1234
The prime factorization of 1234 is 2 617
$ factor 1234
1234: 2 617
$ ./stackoverflow_003
Enter an integer: asd
Something went wrong within scanf(): wrong number of objects read.
$ ./stackoverflow_003
Enter an integer: 123.123
The prime factorization of 123 is 3 41
No, it does not work. Why not? If you ask scanf() to scan an integer it grabs all consecutive decimal digits (0-9) until there is no one left. The little qualifier "consecutive" is most likely the source of your problem: a floating point number with a fractional part has a decimal point and that is the point where scanf() assumes that the integer you wanted ended. Check:
$ ./stackoverflow_003
Enter an integer: .123
Something went wrong within scanf(): wrong number of objects read
How do you find out? #weather-vane gave one of many ways to do so: check if the next character after the integer is a period (or another decimal separator of your choice):
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
int main(void)
{
int x, i, scanf_return;
char c = -1;
printf("Enter an integer: ");
/* Reset "errno". Not necessary here, just in case. */
errno = 0;
/* scanf() returns a value in case of an error */
scanf_return = scanf("%d%c", &x, &c);
/*
* scanf() returns "EOF" if it didn't find all what you wanted or
* and error happened.
* It sets "errno" to the value of the actual error. See manpage
* for all of the details.
*/
if (scanf_return == EOF) {
/*
* The error is connected to the stream, so we can differ between
* an error within scanf() and and error with the input stream
* (here: stdin)
*/
if (ferror(stdin)) {
fprintf(stderr, "Something went wrong while reading stdin: %s\n", strerror(errno));
exit(EXIT_FAILURE);
} else {
/* e.g. a conversion error, a float instead of an integer, letters
instead of a decimal number */
fprintf(stderr, "Something went wrong within scanf()\n");
exit(EXIT_FAILURE);
}
}
/*
* If no error occurred, the return holds the number of objects
* scanf() was able to read. We can use this information now.
* If there is a period (actually any character) after the integer
* it returns 2 (assuming no error happened, of course)
*/
/* If no integer given, the following character ("%c") gets ignored. */
if (scanf_return == 0) {
fprintf(stderr, "Something went wrong within scanf(): no objects read.\n");
exit(EXIT_FAILURE);
}
/* Found two objects, check second one which is the character. */
if (scanf_return == 2) {
if (c == '.') {
fprintf(stderr, "Floating point numbers are not allowed.\n");
exit(EXIT_FAILURE);
}
}
if (x <= 1) {
fprintf(stderr, "Input must be larger than 1!\n");
exit(EXIT_FAILURE);
}
printf("The prime factorization of %d is ", x);
/* No need for that test, x is already larger than one at this point. */
/* if (x > 1) { */
while (x%2 == 0) {
printf("2 ");
x = x / 2;
}
for (i = 3; i < 1009; i = i + 2) {
while (x%i == 0) {
printf("%d ",i);
x = x / i;
}
}
/* } */
/* Make it pretty. */
putchar('\n');
exit(EXIT_SUCCESS);
}
Check:
$ ./stackoverflow_003
Enter an integer: 123
The prime factorization of 123 is 3 41
$ ./stackoverflow_003
Enter an integer: 123.123
Floating point numbers are not allowed.
$ ./stackoverflow_003
Enter an integer: .123
Something went wrong within scanf(): no objects read.
Looks good enough for me. With one little bug:
$ ./stackoverflow_003
Enter an integer: 123.
Floating point numbers are not allowed
But I think I can leave that as an exercise for the dear reader.
You can try this simple C99 implementation of Pollard Rho algorithm :
// Integer factorization in C language.
// Decompose a composite number into a product of smaller integers.
unsigned long long pollard_rho(const unsigned long long N) {
// Require : N is a composite number, not a square.
// Ensure : you already performed trial division up to 23.
// Option : change the timeout, change the rand function.
static const int timeout = 18;
static unsigned long long rand_val = 2994439072U;
rand_val = (rand_val * 1025416097U + 286824428U) % 4294967291LLU;
unsigned long long gcd = 1, a, b, c, i = 0, j = 1, x = 1, y = 1 + rand_val % (N - 1);
for (; gcd == 1; ++i) {
if (i == j) {
if (j >> timeout)
break;
j <<= 1;
x = y; // "x" takes the previous value of "y" when "i" is a power of 2.
}
a = y, b = y; // computes y = f(y)
for (y = 0; a; a & 1 ? b >= N - y ? y -= N : 0, y += b : 0, a >>= 1, (c = b) >= N - b ? c -= N : 0, b += c);
y = (1 + y) % N; // function f performed f(y) = (y * y + 1) % N
for (a = y > x ? y - x : x - y, b = N; (a %= b) && (b %= a););
gcd = a | b; // the GCD(abs(y - x), N) was computed
// it continues until "gcd" is a non-trivial factor of N.
}
return gcd;
}
Usually you performed some trial division before calling the algorithm
The algorithm isn't designed to receive a prime number as input
Two consecutive calls may not result in the same answer
Alternately, there is a pure C quadratic sieve which factors numbers from 0 to 300-bit.
If in doubt about the primality of N you can use a C99 primality checker :
typedef unsigned long long int ulong;
ulong mul_mod(ulong a, ulong b, const ulong mod) {
ulong res = 0, c; // return (a * b) % mod, avoiding overflow errors while doing modular multiplication.
for (b %= mod; a; a & 1 ? b >= mod - res ? res -= mod : 0, res += b : 0, a >>= 1, (c = b) >= mod - b ? c -= mod : 0, b += c);
return res % mod;
}
ulong pow_mod(ulong n, ulong exp, const ulong mod) {
ulong res = 1; // return (n ^ exp) % mod
for (n %= mod; exp; exp & 1 ? res = mul_mod(res, n, mod) : 0, n = mul_mod(n, n, mod), exp >>= 1);
return res;
}
int is_prime(ulong N) {
// Perform a Miller-Rabin test, it should be a deterministic version.
const ulong n_primes = 9, primes[] = {2, 3, 5, 7, 11, 13, 17, 19, 23};
for (ulong i = 0; i < n_primes; ++i)
if (N % primes[i] == 0) return N == primes[i];
if (N < primes[n_primes - 1]) return 0;
int primality = 1, a = 0;
ulong b;
for (b = N - 1; ~b & 1; b >>= 1, ++a);
for (ulong i = 0; i < n_primes && primality; ++i) {
ulong c = pow_mod(primes[i], b, N);
if (c != 1) {
for (int j = a; j-- && (primality = c + 1 != N);)
c = mul_mod(c, c, N);
primality = !primality;
}
}
return primality;
}
To try it there is a factor function :
// return the number that was multiplied by itself to reach N.
ulong square_root(const ulong num) {
ulong res = 0, rem = num, a, b;
for (a = 1LLU << 62 ; a; a >>= 2) {
b = res + a;
res >>= 1;
if (rem >= b)
rem -= b, res += a;
}
return res;
}
ulong factor(ulong num){
const ulong root = square_root(num);
if (root * root == num) return root ;
const ulong n_primes = 9, primes[] = {2, 3, 5, 7, 11, 13, 17, 19, 23};
for (ulong i = 0; i < n_primes && primes[i] <= root; ++i)
if (num % primes[i] == 0) return primes[i];
if (is_prime(num))
return 1 ;
return pollard_rho(num);
}
Which is completed by the main function :
#include <assert.h>
int main(void){
for(ulong i = 2; i < 63; ++i){
ulong f = factor(i);
assert(f <= 1 || f >= i ? is_prime(i) : i % f == 0);
ulong j = (1LLU << i) - 1 ;
f = factor(j);
assert(f <= 1 || f >= j ? is_prime(j) : j % f == 0);
j = 1 | pow_mod((ulong) &main, i, -5);
f = factor(j);
assert(f <= 1 || f >= j ? is_prime(j) : j % f == 0);
}
}
There are some problems in your code:
you do not check the return value of scanf, so you cannot detect invalid or missing input and will have undefined behavior in those cases.
you only test divisors up to 1009, so composite numbers with larger prime factors do not produce any output.
prime numbers larger than 1009 do not produce any output.
you should probably output a newline after the factors.
Testing and reporting invalid input such as floating point numbers can be done more easily by reading the input as a full line and parsing it with strtol().
Here is a modified version:
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
int main() {
char input[120];
char ch;
char *p;
long x, i;
int last_errno;
printf("Enter an integer: ");
if (!fgets(input, sizeof input, stdin)) {
fprintf(stderr, "missing input\n");
return 1;
}
errno = 0;
x = strtol(input, &p, 0);
last_errno = errno;
if (p == input || sscanf(p, " %c", &ch) == 1) {
fprintf(stderr, "invalid input: %s", input);
return 1;
}
if (last_errno == ERANGE) {
fprintf(stderr, "number too large: %s", input);
return 1;
}
if (x < 0) {
fprintf(stderr, "number is negative: %ld\n", x);
return 1;
}
if (x <= 1) {
return 1;
}
printf("The prime factorization of %ld is", x);
while (x % 2 == 0) {
printf(" 2");
x = x / 2;
}
for (i = 3; x / i >= i;) {
if (x % i == 0) {
printf(" %ld", i);
x = x / i;
} else {
i = i + 2;
}
}
if (x > 1) {
printf(" %ld", x);
}
printf("\n");
return 0;
}
I am trying to solve this problem:
Input: the first line contains an integer T which represents the total cases you need to solve. Each test case contains P and Q, separated by space, represent the number you need to work on.
Output: print the result which is calculated from the multiplication of P and Qβs minimum factor and maximum prime factor.
Constraints: 1 β€ π β€ 100 and 2 β€ π,π β€ 1000000
Sample Input: 2 210 84 6 12
Sample Output:
Case #1: 14
Case #2: 6
Explanation: Letβs take an example from the first case. The numbers 210 and 84 have several identical prime factors which are 2, 3, and 7. Number β2β is the smallest common prime factor of the numbers, meanwhile number β7β is their largest common prime factor. So, the result must be the multiplication of 2 and 7, which is 14.
Here's my code that I've been working, I tried to find factors from the given number the store the factors into array then check for the prime, but I feel that this isn't the right algorithm :(
void factor(int num1) {
int arrA[100000], a = 0, flag = 1;
//check factor
for (int i = 2; i <= num1; i++) {
if (num1 % i == 0) {
arrA[a] = i;
a++;
}
}
// check prime
for (int i = 0; i < a; i++) {
for (int j = 2; j < a; j++) {
if ((arrA[i] % j) == 0) {
flag = 0;
}
}
if (flag == 1) {
printf("%d ", arrA[i]);
}
flag = 1;
}
printf("\n");
}
Your function does not compute the prime factors correctly because it will find factors that are not prime. For num = 6, it will find 2, 3 but also 6.
You should divide num by i when you find that i divides num and otherwise increase i.
You can then make arrA much smaller as the maximum number of prime factors in an int is less than the number of bits in an int: 31 would suffice for 32-bit ints and 63 for 64-bit ints.
Once you have the prime factors of num, you should try and find the smallest and largest that divide the other number. Note that the first and last such prime numbers could be identical or might not even exist if the numbers have no common prime factor.
Note that you do not need to store the factors: for every prime factor of num, you can try and check if it divides the other number and keep the first one that does and the last one too.
Here is a simple implementation:
#include <stdio.h>
int main() {
int i, n, a, aa, b, p, p1, p2;
if (scanf("%d", &n) == 1) {
for (i = 1; i <= n; i++) {
if (scanf("%d%d", &a, &b) != 2)
break;
p1 = p2 = 1;
aa = a;
for (p = 2; p * p <= aa; p++) {
if (aa % p == 0) {
/* p is a prime factor of a */
if (b % p == 0) {
/* p is a common prime factor */
p2 = p;
if (p1 == 1) {
/* p is the smallest common prime factor */
p1 = p;
}
}
/* remove p as a factor of aa */
do { aa /= p; } while (aa % p == 0);
}
}
if (aa > 1) {
/* aa is the largest prime factor of a */
if (b % aa == 0) {
/* aa is the largest common prime factor */
p2 = aa;
if (p1 == 1) {
/* aa is also the smallest common prime factor */
p1 = aa;
}
}
}
/* print the product of the smallest and largest common prime factors */
/* if a == b and a is a large prime, a * a might overflow int */
printf("Case #%d: %lld\n", i, (long long)p1 * p2);
}
}
return 0;
}
I have to create a minimal prime generator in C (we need the minimal primes that have at least two digits) and i cannot use tables.So my thought was first find all the primes,second with using masks to find all the subsequences of each number and finally check if every subsequence is not a prime number.i cannot find the minimal primes because i didnt put a condition to check if a subsequence is prime or no?(my code is not ready so it may have some mistakes but it runs)
my code
#include <stdio.h>
#define MAXNUMB 100
int main ()
{
int i,j,x,mask,max=1,mult,sub;
for (i = 11 ; i < MAXNUMB; i += 2 ) {
for (j = 3; j * j <= i; j += 2) {
if (i % j == 0) {
break;
}
}
if (j * j > i) {
int length = 0;
int tmp=i;
while (tmp != 0) {
tmp /= 10;
length++;
}
for (x=1;x<length*2;x++) {
mask=x;
mult=1;
sub=0;
int num=i;
while ( num != 0 ) {
if ( mask % 2 == 1 ) {
sub += num % 10 * mult;
mult *= 10;
}
num /= 10;
mask /= 2;
}
printf ("%d \n",sub);
}
printf ("%d is minimal prime \n",i);
}
}
}
If MAXNUMB is not too large then you can very quickly find all the primes until MAXNUMB using the Sieve_of_Eratosthenes. After you have that you can get every subsequence of an n-digit number by counting from 1 to 2^n-1 and use the bit-pattern of the current count to specify the current subsequence. Check each subsequence in the sieve.
If MAXNUMB is too big then you can build the sieve up to sqrt(MAXNUMB), so that when you test a number whether it's prime or not you just have to check whether it's divisible with any prime, instead of checking whether it's divisible any odd number.
Wikipedia has a nice pseudocode algorithm for primality. It's naive, but it works.
function is_prime(n : integer)
if n β€ 1
return false
else if n β€ 3
return true
else if n mod 2 = 0 or n mod 3 = 0
return false
let i β 5
while iΓi β€ n
if n mod i = 0 or n mod (i + 2) = 0
return false
i β i + 6
return true
I'll leave translating this into C for you. My one note is that i should be of a type larger than n's type. For the reason, consider what happens to iΓi β€ n when n is the largest integer.
When you're ready, you can look at my solution to this problem.
The concept of a minimal prime is moderately interesting. I wrote the following code to do the checking.
/* SO 33838621: Minimal Primes */
/*
** Find the minimal primes less than 100,000.
**
** A minimal prime is a prime number for which no subsequence of the digits
** that make up the number is itself prime.
** The question gives two examples:
** = 881 is prime and is a minimal prime because none of { 8, 8, 1, 88,
** 81, 81 } are prime.
** = 109 is prime but is not a minimal prime because { 1, 0, 9, 10, 9,
** 19 } includes the prime 19.
** Clearly, the single digit primes are all trivially minimal.
**
** Additional wrinkle: the code may not build up a table of primes.
**
** NB: All primes except 2 and 3 have the form 6NΒ±1
*/
/*
** There are two problems to solve:
** (1) Check for primality without using a table of primes.
** (2) Generate all subsequences of a number.
** The latter problem is somewhat harder than the former.
** The surviving solution uses recursive string manipulation.
**
** NB: Command subsequences is derived from this, and helps check
** the validity of the minimal primes.
*/
#include <assert.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static bool is_prime(int n)
{
if (n < 2)
return false;
if (n == 2 || n == 3 || n == 5 || n == 7)
return true;
if (n % 2 == 0 || n % 3 == 0 || n % 5 == 0 || n % 7 == 0)
return false;
for (int c = 12; (c - 1) * (c - 1) <= n; c += 6)
{
if (n % (c - 1) == 0 || n % (c + 1) == 0)
return false;
}
return true;
}
static bool has_prime_n_digit_subset(int p0, int n_digits, const char *buffer, int buflen)
{
//printf("-->> p0 = %5d, n = %d (%s)\n", p0, n_digits, buffer);
assert(buflen >= 0 && strlen(buffer) == (size_t)buflen);
for (int i = 0; i < buflen; i++)
{
int p1 = 10 * p0 + buffer[i] - '0';
if (n_digits > 1)
{
if (has_prime_n_digit_subset(p1, n_digits - 1, &buffer[i+1], buflen - i - 1))
{
//printf("<<-- true\n");
return true;
}
}
else
{
//printf("C %d\n", p1);
if (is_prime(p1))
{
//printf("<<-- p1 = %d: true\n", p1);
return true;
}
}
}
//printf("<<-- false\n");
return false;
}
static void check_minimal_prime(int n)
{
assert(n > 0);
if (is_prime(n))
{
//printf("P %d\n", n);
char buffer[20];
sprintf(buffer, "%d", n);
char n_digits = strlen(buffer);
for (int i = 1; i < n_digits; i++)
{
if (has_prime_n_digit_subset(0, i, buffer, n_digits))
return;
}
printf("%d\n", n); /* It's a minimal prime */
}
}
int main(int argc, char **argv)
{
int max = 100000;
if (argc > 2)
{
fprintf(stderr, "Usage: %s [maximum]\n", argv[0]);
exit(1);
}
else if (argc == 2)
{
max = atoi(argv[1]);
if (max <= 0)
{
fprintf(stderr, "Invalid number (%d from %s)\n", max, argv[1]);
exit(1);
}
}
max /= 6;
check_minimal_prime(2);
check_minimal_prime(3);
for (int c = 1; c < max; c++)
{
check_minimal_prime(6 * c - 1);
check_minimal_prime(6 * c + 1);
}
return 0;
}
The list of numbers generated was:
2
3
5
7
11
19
41
61
89
409
449
499
881
991
6469
6949
9001
9049
9649
9949
60649
666649
946669
60000049
66000049
66600049
I didn't find any more minimal primes when checking up to 1,000,000,000. Timing was:
100 0m0.006s
1000 0m0.006s
10000 0m0.006s
100000 0m0.012s
1000000 0m0.129s
10000000 0m2.617s
100000000 1m8.200s
1000000000 32m34.561s
I am accepting a composite number as an input. I want to print all its factors and also the largest prime factor of that number. I have written the following code. It is working perfectly ok till the number 51. But if any number greater than 51 is inputted, wrong output is shown. how can I correct my code?
#include<stdio.h>
void main()
{
int i, j, b=2, c;
printf("\nEnter a composite number: ");
scanf("%d", &c);
printf("Factors: ");
for(i=1; i<=c/2; i++)
{
if(c%i==0)
{
printf("%d ", i);
for(j=1; j<=i; j++)
{
if(i%j > 0)
{
b = i;
}
if(b%3==0)
b = 3;
else if(b%2==0)
b = 2;
else if(b%5==0)
b = 5;
}
}
}
printf("%d\nLargest prime factor: %d\n", c, b);
}
This is a bit of a spoiler, so if you want to solve this yourself, don't read this yet :). I'll try to provide hints in order of succession, so you can read each hint in order, and if you need more hints, move to the next hint, etc.
Hint #1:
If divisor is a divisor of n, then n / divisor is also a divisor of n. For example, 100 / 2 = 50 with remainder 0, so 2 is a divisor of 100. But this also means that 50 is a divisor of 100.
Hint #2
Given Hint #1, what this means is that we can loop from i = 2 to i*i <= n when checking for prime factors. For example, if we are checking the number 100, then we only have to loop to 10 (10*10 is <= 100) because by using hint #1, we will get all the factors. That is:
100 / 2 = 50, so 2 and 50 are factors
100 / 5 = 20, so 5 and 20 are factors
100 / 10 = 10, so 10 is a factor
Hint #3
Since we only care about prime factors for n, it's sufficient to just find the first factor of n, call it divisor, and then we can recursively find the other factors for n / divisor. We can use a sieve approach and mark off the factors as we find them.
Hint #4
Sample solution in C:
bool factors[100000];
void getprimefactors(int n) {
// 0 and 1 are not prime
if (n == 0 || n == 1) return;
// find smallest number >= 2 that is a divisor of n (it will be a prime number)
int divisor = 0;
for(int i = 2; i*i <= n; ++i) {
if (n % i == 0) {
divisor = i;
break;
}
}
if (divisor == 0) {
// we didn't find a divisor, so n is prime
factors[n] = true;
return;
}
// we found a divisor
factors[divisor] = true;
getprimefactors(n / divisor);
}
int main() {
memset(factors,false,sizeof factors);
int f = 1234;
getprimefactors(f);
int largest;
printf("prime factors for %d:\n",f);
for(int i = 2; i <= f/2; ++i) {
if (factors[i]) {
printf("%d\n",i);
largest = i;
}
}
printf("largest prime factor is %d\n",largest);
return 0;
}
Output:
---------- Capture Output ----------
> "c:\windows\system32\cmd.exe" /c c:\temp\temp.exe
prime factors for 1234:
2
617
largest prime factor is 617
> Terminated with exit code 0.
I presume you're doing this to learn, so I hope you don't mind a hint.
I'd start by stepping through your algorithm on a number that fails. Does this show you where the error is?
You need to recode so that your code finds all the prime numbers of a given number, instead of just calculating for the prime numbers 2,3, and 5. In other words, your code can only work with the number you are calculating is a prime number or is a multiple of 2, 3, or 5. But 7, 11, 13, 17, 19 are also prime numbers--so your code should simply work by finding all factors of a particular number and return the largest factor that is not further divisible.
Really, this is very slow for all but the smallest numbers (below, say, 100,000). Try finding just the prime factors of the number:
#include <cmath>
void addfactor(int n) {
printf ("%d\n", n);
}
int main()
{
int d;
int s;
int c = 1234567;
while (!(c&1)) {
addfactor(2);
c >>= 1;
}
while (c%3 == 0) {
addfactor(3);
c /= 3;
}
s = (int)sqrt(c + 0.5);
for (d = 5; d <= s;) {
while (c % d == 0) {
addfactor(d);
c /= d;
s = (int)sqrt(c + 0.5);
}
d += 2;
while (c % d == 0) {
addfactor(d);
c /= d;
s = (int)sqrt(c + 0.5);
}
d += 4;
}
if (c > 1)
addfactor(c);
return 0;
}
where addfactor is some kind of macro that adds the factor to a list of prime factors. Once you have these, you can construct a list of all the factors of the number.
This is dramatically faster than the other code snippets posted here. For a random input like 10597959011, my code would take something like 2000 bit operations plus 1000 more to re-constitute the divisors, while the others would take billions of operations. It's the difference between 'instant' and a minute in that case.
Simplification to dcp's answer(in an iterative way):
#include <stdio.h>
void factorize_and_print(unsigned long number) {
unsigned long factor;
for(factor = 2; number > 1; factor++) {
while(number % factor == 0) {
number = number / factor;
printf("%lu\n",factor);
}
}
}
/* example main */
int main(int argc,char** argv) {
if(argc >= 2) {
long number = atol(argv[1]);
factorize_and_print(number);
} else {
printf("Usage: %s <number>%<number> is unsigned long", argv[0]);
}
}
Note: There is a number parsing bug here that is not getting the number in argv correctly.