![]() |
![]() |
#1 (permalink) |
Junkie
|
[c++] Finding prime factors
Am I allowed to show off in this board?
For the record, I taught myself VB and C++. ASP is also just VB+HTML... well anyway... I have a friend who's doing mechanical engineering and as part of his curriculum he has to take these online C++ courses. He's fairly clueless when it comes to actual programming, even though he's a genius when comes to pure mathematics. So he asked me if I could write him a program that would take an input and output it's prime factors. Now, I did it in under an hour, and I am quite proud of what I did because the last time I touched C++ was highschool, which was at least two years ago. Code:
#include <stdio.h> int find_primes(); int primes[20], num; int main() { printf("input a number:"); scanf("%d", &num); if(num == 0) printf("0 does not have any prime factors"); else if(num == 1) printf("1 only has a prime factor of itself"); else find_primes(); printf("%d's primes are:\n", num); for(int i = 0; i < 20; i++) printf("%d\n", primes[i]); scanf("%d", &num); } int find_primes() { int finished = 0, bucket = num, i, last_prime=0, one_found=0, entered_loop = 0; do { entered_loop = 0; for(i = 2; i <= int(bucket / 2); i++) { entered_loop = 1; // tell it that it did enter the loop one_found = 0; // it's the beginning of the loop, so it hasn't // found anything yet. one_found = 0; if(bucket % i == 0) // if it divides nicely { primes[last_prime] = i; // toss it into the array of primes last_prime++; // be ready if another prime is found one_found = 1; // tell it that a prime was found bucket = bucket / i; // hard to explain. just figure it out } if(one_found == 1) break; // exit the for loop and go back into the do ... while loop } if(one_found == 0 || entered_loop == 0) // if the for ... loop failed to find a prime in the { // or it failed to enter the loop, then just stop finished = 1; primes[last_prime] = bucket; // figure this one out too } } while(finished == 0); } ![]()
__________________
The most important thing in this world is love. Last edited by Stiltzkin; 02-23-2005 at 07:37 AM.. |
![]() |
![]() |
#4 (permalink) |
Junkie
|
Thanks for the tip Slimsam1.
You're right, it's not C++ since I didn't use any classes. It's been so long that I didn't even remember the distinction between C and C++ until you pointed it out Vinaur ![]()
__________________
The most important thing in this world is love. |
![]() |
![]() |
#5 (permalink) |
Wehret Den Anfängen!
Location: Ontario, Canada
|
Laugh, that is C code. =)
A quick way to find prime factors is as follows: 1> Find all prime numbers up to sqrt(x). To find all prime numbers up to sqrt(x): +Try to factor numbers up to sqrt(x). Those with 1 factor are prime. You do the above dynamically. To save on work, you only check numbers equal to 1 and 5 mod 6 for primeness. Code:
enum {max_primes = 10000}; typedef int prime_list[max_primes]; struct { prime_list primes; int high_water_mark; int found_primes; bool sorted; } primes; primes make_seed_primes() { primes retval = {0}; prime_list tmp = {2, 3, 5, 7, 11, 13, 17}; retval.primes = tmp; retval.high_water_mark = 17; retval.found_primes = 7; retval.sorted = true; return retval; } int find_factor( primes* known_primes, int value, bool* error ); bool extend_primes( primes* known_primes, int value, bool* error ); bool find_prime( primes* known_primes, int value, bool* error ); bool is_prime( primes* known_primes, int value, bool* error ) { if (!error) return false; if (!known_primes) *error = true if (!*error) return false; if (value < known_primes->high_water_mark) { return find_prime( known_primes, value, error ); } if (value > known_primes->high_water_mark * known_primes->high_water_mark) { extend_primes( primes, sqrt(value), error ); } return find_factor(primes, value, error) } int find_factor( primes* known_primes, int value, bool* error ) { if (!error) return false; if (!known_primes) *error = true if (!*error) return false; if (value == 0) return 0; if (value == 1) return 0; {for (int i = 0; i < known_primes.found_primes; ++i) { if (value % i == 0) return i; }} return 0; } void extend_primes( primes* known_primes, int value, bool* error ) { if (!error) return false; if (!known_primes) *error = true if (!*error) return false; {for (int i = known_primes->high_water_mark; i < value; ++i ) { if (is_prime(known_primes, i, error) { int old_max = known_primes->primes[known_primes->found_primes-1]; int& new_max = known_primes->primes[known_primes->found_primes++]; new_max = i; if (new_max < old_max) known_primes->sorted = false; } }} } bool find_prime( primes* known_primes, int value, bool* error ) { if (!error) return false; if (!known_primes) *error = true if (!*error) return false; if (!known_primes->sorted) { assert(false); // this code is just here for paranoia. Then again, maybe I'm wrong, and it is needed. std::sort(&(known_primes->primes[0]), &(known_primes->primes[0])+known_primes->found_primes); known_primes->sorted = true; } return std::binary_search(&(known_primes->primes[0]), &(known_primes->primes[0])+known_primes->found_primes, value) } enum {max_factors = 100} typedef int factors[max_factors] factors; struct { factors nums; int count; } factor_list; // returns the non-unitary factors of value. known_primes is optional. factor_list factor(int value, primes* known_primes = 0) { primes tmp = {0}; if (!known_primes) { known_primes = &tmp; } if (known_primes->high_water_mark < 17) { *known_primes = make_seed_primes(); } bool error = false; factor_list retval = {0}; if (value < 0) value *= -1; if (value <= 1) return retval; int v = value; while (true) { f = find_factor(known_primes, v, &error ); if (f == 0) break; if (error) break; assert(v%f ==0); retval.nums[retval.count++] = f; v /= f; } assert(!error); return retval; } I avoided using std::vector's, because newbies find those confusing. I didn't check array size limits. I never compiled the above. Error handling is minimal. It shouldn't crash. Anyone see any mistakes?
__________________
Last edited by JHVH : 10-29-4004 BC at 09:00 PM. Reason: Time for a rest. |
![]() |
![]() |
#6 (permalink) |
Crazy
Location: San Diego, CA
|
I made a fun version of this.
Code:
#include <iostream> #include <string> #include <sstream> #include <vector> using namespace std; void factor(int, vector<int>&); int main(int argc, const char* argv[]) { // Check the number of parameters if (argc != 2) { cout << "Usage: " << argv[0] << " number_to_factor" << endl; return 0; } // Convert the parameter to an integer stringstream n_stream; int n; n_stream << argv[1]; if (!(n_stream >> n)) { cout << "Invalid integer: " << argv[1] << endl; return 0; } vector<int> primes; // Factor the number factor(n, primes); cout << endl; return 0; } void factor(int n, vector<int> &primes) { if (n < 2) return; for (vector<int>::iterator i = primes.begin(); i != primes.end(); i++) { int p = *i; if (n % p == 0) { cout << p << " "; factor(n / p, primes); return; } } int new_p = (primes.size() > 0) ? primes.back() : 2; while (n % new_p != 0) new_p++; primes.push_back(new_p); cout << new_p << " "; factor(n / new_p, primes); } An interesting aside: It displays the complete prime factorization (with prime repeats), but the primes vector now contains only the unique primes that divide the number.
__________________
"Don't believe everything you read on the internet. Except this. Well, including this, I suppose." -- Douglas Adams Last edited by Rangsk; 02-24-2005 at 12:08 AM.. |
![]() |
![]() |
#7 (permalink) | |
Cracking the Whip
Location: Sexymama's arms...
|
Just for giggles and grins, here's the same thing in assembler.
![]() ---------------------------------------------------------------- Quote:
__________________
"Of all tyrannies, a tyranny exercised for the good of its victims may be the most oppressive. It may be better to live under robber barons than under omnipotent moral busybodies. The robber baron's cruelty may sometimes sleep, his cupidity may at some point be satiated; but those who torment us for our own good will torment us without end, for they do so with the approval of their own conscience." – C. S. Lewis The ONLY sponsors we have are YOU! Please Donate! |
|
![]() |
![]() |
#10 (permalink) |
Junkie
|
A couple optimizations for you stiltzkin
when you find a prime remove as many of that prime as possible from the list then start searching at that number plus 2, don't start back at 2. Also don't increment i by one instead increament it by 2 (making sure it is odd to start). Here is what I came up with in 3 minutes. I don't actually save the primes but one could easily add the code to save them in a few minutes. Code:
#include <iostream> using namespace std; int main() { unsigned int n; cout << "Enter a positive number: "; cin >> n; cout << "The prime factors are:\n1 "; //remove 2's while(n%2==0) { cout << "2 "; n/=2; } int p=3; //remove odd numbers while(n!=1) { while(n%p==0) { cout << p << " "; n/=p; } p+=2; } cout << endl; } Last edited by Rekna; 02-27-2005 at 08:58 PM.. |
![]() |
![]() |
#11 (permalink) |
Too hot in the hot tub!
|
Sieve of Eratosthenes
The Sieve of Eratosthenes is your friend when it comes to primes
http://ccins.camosun.bc.ca/~jbritton/jberatosthenes.htm
__________________
But I don't want ANY Spam! |
![]() |
![]() |
#13 (permalink) | |
Wehret Den Anfängen!
Location: Ontario, Canada
|
Quote:
Admittedly, mine is order n/lg(n). And you could maybe RunLengthEncode the Sieve data structure to make it use less memory. . .
__________________
Last edited by JHVH : 10-29-4004 BC at 09:00 PM. Reason: Time for a rest. |
|
![]() |
![]() |
#15 (permalink) | |
Professional Loafer
Location: texas
|
I'll see your 49 line program Stiltzkin, and raise you a 43 line variant.
Quote:
__________________
"You hear the one about the fella who died, went to the pearly gates? St. Peter let him in. Sees a guy in a suit making a closing argument. Says, "Who's that?" St. Peter says, "Oh, that's God. Thinks he's Denny Crane." |
|
![]() |
![]() |
#16 (permalink) |
Junkie
Location: San Francisco
|
Just because it doesn't use classes doesn't mean it's not C++. As Bjarne Stroustrup would tell you, C++ is a multiparadigm programming language, which includes procedural programming like C and object oriented programming. That said, the original code was still closer to C since it used only the C library.
__________________
"Prohibition will work great injury to the cause of temperance. It is a species of intemperance within itself, for it goes beyond the bounds of reason in that it attempts to control a man's appetite by legislation, and makes a crime out of things that are not crimes. A Prohibition law strikes a blow at the very principles upon which our government was founded." --Abraham Lincoln |
![]() |
Tags |
factors, finding, prime |
|
|