I am trying to create a function to find the square root of a number. For debugging purposes, it has instructions to print current variable values. The function squareRoot accepts two arguments, x and t. It then declares and initializes n and s. n is the amount to add or subtract, halving every time it is used. s is what is thought to be the current square root. When running, I can clearly see that n is adjusting correctly. However, s stops changing when the first four digits are correct. I am using this call in main():
cout << squareRoot(1000, 10) << "\n";
This should print the square root of 1000 to the nearest tenth, but two weird things happen:
It doesn't stop at 31.6.
It stops at 4 digits!
My theory as to why it stops at four digits is this: In multiplying, s loses some of its precision. Is this true? If so, can you tell me how to correct it? If not, what is causing this and how can I correct that?
I tried to solve it already by using another variable, s1, which would be multiplied and checked. Then s would be incremented by n, and s1 synchronized with s. This didn't work, so I went back to the original code.
My code is as follows:
#include <iostream>
using namespace std;
double squareRoot(double x, int t) {
double s = 0;
double n = 0.1;
while ((s*s) <= x) {
s += n;
n *= 2;
cout << n << "\n" << s << "\n";
}
cout << "\n";
s -= n;
// Keep changing until margin of error is reached
while ((((s*s) - x) < (1/t)) || ((x - (s*s) < (1/t)))) {
// If too high, lower s
if ((s*s) <= x) {
s += n;
n /= 2;
cout << "Adding 1/2 of previous n\n";
}
// If too low, raise s
else if ((s*s) >= x) {
s -= n;
n /= 2;
cout << "Subtracting 1/2 of previous n\n";
}
cout << s << "\n" << n << "\n\n";
}
return s;
}
I am running Windows 7 64 bit, MSVC++ 2008 Express. Thank you in advance for all answers!
It converges to the correct square root, but cout only prints six significant digits by default: 31.xxxx.
Also notice that your termination check does not work because (1/t) will always evaluate to 0 for t>1. Use 1./t instead.
Unrelated, but your sqrt algorithm can be sped up by using an existing one, such as Newton's Method.
It goes like this:
double mySqrt(double x, unsigned long accuracy = 10)
{
if(x < 0.0)
return(-1.0);
double retval = 1.0;
for(unsigned long rep = 0; rep < accuracy; rep++)
retval = ((x / retval) + retval) / 2.0;
return(retval);
}
Newton's method also works for cube roots, etc.
For decimal exponents, look up the Binomial Theorem.
The reason loop isn't stopping is that loop condition isn't correct. You have
while ((current - target < precision) || (target - current < precision)) {
...
}
But either value current - target or value target - current will be <= 0. And 0 < precision. Thus you have equivalent of while (true) {...} loop.
You need something like
while (abs(current - target) > precision) {
...
}
(don't know exact function for getting absolute value in C++)
edit
Just noticed, hamster3null wrote about 1/t before me.
Related
So I am trying to find the number of digits in a given int. The way I opted to find the digits was to divide the given int by powers of 10. Since I would be dividing by integers, the code would eventually reach a 0 when 10 is raised to a high enough power. There would be a tracker that tracks every iteration of this and that tracker would be able to tell me how digits there were.
#include <cmath>
#include <iostream>
int findDigits(int x)
{
//tracks the digits of int
int power{ 0 };
for (int i = 0; x / pow(10, i) != 0; i++) //the condition is not working as it should
{
//I checked the math expression and it is getting the intended result of zero at i = 3
int quotient = x / pow(10, i);
//I then checked the condition and it is becoming false when the expression results in 0
bool doesWork;
if (x / pow(10, i) != 0)
doesWork = true;
else
doesWork = false;
power = i;
}
return power;
}
int main()
{
std::cout << "157 has " << findDigits(157) << " digits";
return 0;
}
First, you are NOT dividing it by integer. pow() returns double according to the c++ reference. Therefore, the result of x / pow(10, i) would be double. ruining everything.
There is two option:
Use x / (int)pow(10, i) != 0 within the for loop condition. And PLUS 1 to the result.
But be aware, floating result of pow() might be corrupted.
If you don't have decent reason to use pow(), stick to the second option.
Go with below for loop instead.
for (; x != 0; x /= 10) {
power++;
}
It divides original number x by 10 until it reaches 0.
I'm supposed to write a small code that generates a random number between 2 and 100 and then checks if its a perfect number. I don't get any bugs from the compiler but the output doesn't show my cout lines like " x is a perfect number". Can someone help me with finding the reason?
#include <iostream>
#include <ctime>
#include <cstdlib>
using namespace std;
bool PerfectCheck(int x) {
int t; // divisor
int sum; // sum of divisors
for (t = 0; t <= x; t++ ) {
if (x%t == 0) {
sum = sum + t;
}
}
if (sum == x)
return true;
else
return false;
}
int main() {
srand(time(NULL));
int x = rand()%(100-2+1)+2;
if (PerfectCheck(x) == true )
cout << x << "is a perfect number.";
else
cout << x << "is not a perfect number.";
return 0;
}
There are three problems in your PerfectCheck function. First, you don't initialize the sum variable, so it can start off with any value whatsoever; you should set it to zero explicitly in the declaration.
Second, your for loop starts with t as zero, and you check x % t. The modulo operator implicitly involves a division, so using a left-hand value of zero has the same issue as trying to divide by zero, which will cause a crash.
Third, when checking for a perfect number, don't use that number itself in the sum; so, stop your loop with t < x instead of t <= x.
Also, as mentioned in the comments, you can simplify the return statement. The code below works, in the tests I have performed:
bool PerfectCheck(int x)
{
int sum = 0; // sum of divisors - MUST BE INITIALIZED (to zero)
for (int t = 1; t < x; t++) { // DO NOT INCLUDE X ITSELF!!
if (x % t == 0) {
sum += t;
}
}
return (sum == x); // This will already give a "true" or "false" bool value.
}
You could actually make the code a tiny bit more 'efficient', by initializing sum to 1 and then starting the loop from t = 2 (all numbers divide by 1, after all).
Feel free to ask for further clarification and/or explanation.
if (x%t == 0) calculates the remainder after dividing x by t and compares the result with 0. That statement is correct, but look at the previous code for (t = 0; t <= x; t++ ) {. The first value of t is 0, so you have a division by zero. More than likely that is crashing your program which is why you see no output. Change for (t = 0; t <= x; t++ ) { to for (t = 1; t <= x; t++ ) {.
Also I believe the definition of a perfect number does not include division by the number itself. So the for loop should actually be for (t = 1; t < x; t++ ) {.
Finally you are using the sum variable to add up the divisors but you do not give it an initial value. Your code should say int sum = 0;.
Three errors in a ten line program (plus various style issues). Imagine how many errors here might be in a 5000 line program. Programming is tricky, you have to be very focused and get your code exactly right, nearly right is not good enough.
I would like to find the largest prime factor of a given number. After several attempts, I've enhanced the test to cope with rather big numbers (i.e. up to one billion in milliseconds). The problem is now if go beyond one billion, the execution time goes forever, so to speak. I wonder if I can do more improvements and reduce the execution time. I'm hoping for better execution time because in this link Prime Factors Calculator, the execution time is incredibly fast. My target number at this moment is 600851475143. The code is rather self-explanatory. Note: I've considered Sieve of Eratosthenes algorithm with no luck regarding the execution time.
#include <iostream>
#include <cmath>
bool isPrime(int n)
{
if (n==2)
return true;
if (n%2==0)
return false;
for (int i(3);i<=sqrt(n);i+=2) // ignore even numbers and go up to sqrt(n)
if (n%i==0)
return false;
return true;
}
int main()
{
int max(0);
long long target(600851475143);
if( target%2 == 0 )
max = 2;
for ( int i(3); i<target; i+=2 ){ // loop through odd numbers.
if( target%i == 0 ) // check for common factor
if( isPrime(i) ) // check for prime common factor
max = i;
}
std::cout << "The greatest prime common factor is " << max << "\n";
return 0;
}
One obvious optimization that I can see is:
for (int i(3);i<=sqrt(n);i+=2) // ignore even numbers and go up to sqrt(n)
instead of calculating sqrt everytime you can cache the result in a variable.
auto maxFactor = static_cast<int>sqrt(n);
for (int i(3); i <= maxFactor; i+=2);
The reason I believe this could lead to speed up is sqrt deals with floating point arithematic and compilers usually aren't generous in optimizing floating point arithematic. gcc has a special flag ffast-math to enable floating point optimizations explicitely.
For numbers upto the target range that you mentioned, you will need better algorithms. repeated divisioning should suffice.
Here is the code (http://ideone.com/RoAmHd) which hardly takes any time to finish:
int main() {
long long input = 600851475143;
long long mx = 0;
for (int x = 2; x <= input/x; ++x){
while(input%x==0) {input/=x; mx = x; }
}
if (input > 1){
mx = input;
}
cout << mx << endl;
return 0;
}
The idea behind repeated division is if a number is already a factor of p, it is also a factor of p^2, p^3, p^4..... So we keep eliminating factors so only prime factors remain that eventually get to divide the number.
You don't need a primality test. Try this algorithm:
function factors(n)
f := 2
while f * f <= n
if n % f == 0
output f
n := n / f
else
f := f + 1
output n
You don't need a primality test because the trial factors increase by 1 at each step, so any composite trial factors will have already been handled by their smaller constituent primes.
I'll leave it to you to implement in C++ with appropriate data types. This isn't the fastest way to factor integers, but it is sufficient for Project Euler 3.
for ( int i(3); i<target; i+=2 ){ // loop through odd numbers.
if( target%i == 0 ) // check for common factor
if( isPrime(i) ) // check for prime common factor
max = i;
It is the first two lines of this code, not primality checks, which take almost all time. You divide target to all numbers from 3 to target-1. This takes about target/2 divisions.
Besides, target is long long, while i is only int. It is possible that the size is too small, and you get an infinite loop.
Finally, this code does not calculate the greatest prime common factor. It calculate the greatest prime divisor of target, and does it very inefficiently. So what do you really need?
And it is a bad idea to call anything "max" in c++, because max is a standard function.
Here is my basic version:
int main() {
long long input = 600851475143L;
long long pMax = 0;
// Deal with prime 2.
while (input % 2 == 0) {
input /= 2;
pMax = 2;
}
// Deal with odd primes.
for (long long x = 3; x * x <= input; x += 2) {
while (input % x == 0) {
input /= x;
pMax = x;
}
}
// Check for unfactorised input - must be prime.
if (input > 1) {
pMax = input;
}
std::cout << "The greatest prime common factor is " << pMax << "\n";
return 0;
}
It might be possible to speed things up further by using a Newton-Raphson integer square root method to set up a (mostly) fixed limit for the loop. If available that would need a rewrite of the main loop.
long long limit = iSqrt(input)
for (long long x = 3; x <= limit; x += 2) {
if (input % x == 0) {
pMax = x;
do {
input /= x;
} while (input % x == 0);
limit = iSqrt(input); // Value of input changed so reset limit.
}
}
The square root is only calculated when a new factor is found and the value of input has changed.
Note that except for 2 and 3, all prime numbers are adjacent to multiples of 6.
The following code reduces the total number of iterations by:
Leveraging the fact mentioned above
Decreasing target every time a new prime factor is found
#include <iostream>
bool CheckFactor(long long& target,long long factor)
{
if (target%factor == 0)
{
do target /= factor;
while (target%factor == 0);
return true;
}
return false;
}
long long GetMaxFactor(long long target)
{
long long maxFactor = 1;
if (CheckFactor(target,2))
maxFactor = 2;
if (CheckFactor(target,3))
maxFactor = 3;
// Check only factors that are adjacent to multiples of 6
for (long long factor = 5, add = 2; factor*factor <= target; factor += add, add = 6-add)
{
if (CheckFactor(target,factor))
maxFactor = factor;
}
if (target > 1)
return target;
return maxFactor;
}
int main()
{
long long target = 600851475143;
std::cout << "The greatest prime factor of " << target << " is " << GetMaxFactor(target) << std::endl;
return 0;
}
I am working on a program in which I must print out the number of primes, including 1 and 239, from 1 - 239 ( I know one and or two may not be prime numbers, but we will consider them as such for this program) It must be a pretty simple program because we have only gone over some basics. So far my code is as such, which seems like decent logical flow to me, but doesnt produce output.
#include <iostream>
using namespace std;
int main()
{
int x;
int n = 1;
int y = 1;
int i = 0;
while (n<=239)
{x = n % y;
if (x = 0)
i++;
if (y < n)
y++;
n++;
while (i == 2)
cout << n;
}
return 0;
}
The way I want this to work is to take n, as long as n is 239 or less, and preform modulus division with every number from 1 leading up to n. Every time a number y goes evenly into n, a counter will be increased by 1. if the counter is equal to 2, then the number is prime and we print it to the screen. Any help would be so greatly appreciated. Thanks
std::cout << std::to_string(2) << std::endl;
for (unsigned int i = 3; i<240; i += 2) {
unsigned int j = 3;
int sq = sqrt(i);
for (; j <= sq; j += 2) if (!(i%j)) break;
if (j>sq) std::cout << std::to_string(i) << std::endl;
}
first of all, the prime definition: A prime number (or a prime) is a natural number greater than 1 that has no positive divisors other than 1 and itself.
so you can skip all the even numbers (and hence ... i+=2).
Moreover no point to try to divide for a number greater than sqrt(i), because then it will have a divisor less than sqrt(i) and the code finds that and move to the next number.
Considering only odd numbers, means that we can skip even numbers as divisors (hence ... j+=2).
In your code there are clearly beginner errors, like (x = 0) instead of x==0. but also the logic doesn't convince. I agree with #NathanOliver, you need to learn to use a debugger to find all the errors. For the rest, good luck with the studies.
lets start with common errors:
first you want to take input from user using cin
cin>>n; // write it before starting your while loop
then,
if (x = 0)
should be:
if (x == 0)
change your second while loop to:
while (i == 2){
cout << n;
i++;
}
I tried a code on a coding website to find the largest prime factor of a number and it's exceeding the time limit for the last test case where probably they are using a large prime number. Can you please help me to reduce the complexity of the following code?
int main()
{
long n;
long int lar, fact;
long int sqroot;
int flag;
cin >> n;
lar=2, fact=2;
sqroot = sqrt(n);
flag = 0;
while(n>1)
{
if((fact > sqroot) && (flag == 0)) //Checking only upto Square Root
{
cout << n << endl;
break;
}
if(n%fact == 0)
{
flag = 1;
lar = fact;
while(n%fact == 0)
n = n/fact;
}
fact++;
}
if(flag == 1) //Don't display if loop fact reached squareroot value
cout << lar << endl;
}
Here I've also taken care of the loop checking till Square Root value. Still, how can I reduce its complexity further?
You can speed things up (if not reduce the complexity) by supplying a hard-coded list of the first N primes to use for the initial values of fact, since using composite values of fact are a waste of time. After that, avoid the obviously composite values of fact (like even numbers).
You can reduce the number of tests by skipping even numbers larger than 2, and stopping sooner if you have found smaller factors. Here is a simpler and faster version:
int main() {
unsigned long long n, lar, fact, sqroot;
cin >> n;
lar = 0;
while (n && n % 2 == 0) {
lar = 2;
n /= 2;
}
fact = 3;
sqroot = sqrt(n);
while (fact <= sqroot) {
if (n % fact == 0) {
lar = fact;
do { n /= fact; } while (n % fact == 0);
sqroot = sqrt(n);
}
fact += 2;
}
if (lar < n)
lar = n;
cout << lar << endl;
return 0;
}
I am not sure how large the input numbers may become, using the larger type unsigned long long for these computations will get you farther than long. Using a precomputed array of primes would help further, but not by a large factor.
The better result I've obtained is using the function below (lpf5()). It's based on the primality() function (below) that uses the formulas 6k+1, 6k-1 to individuate prime numbers. All prime numbers >= 5 may be expressed in one of the forms p=k*6+1 or p=k*6-1 with k>0 (but not all the numbers having such a forms are primes). Developing these formulas we can see a sequence like the following:
k=1 5,7
k=2 11,13
k=3 17,19
k=4 23,25*
k=5 29,31
.
.
.
k=10 59,61
k=11 65*,67
k=12 71,73
...
5,7,11,13,17,19,23,25,29,31,...,59,61,65,67,71,73,...
We observe that the difference between the terms is alternatively 2 and 4. Such a results may be obtained also using simple math. Is obvious that the difference between k*6+1 and k*6-1 is 2. It's simple to note that the difference between k*6+1 and (k+1)*6-1 is 4.
The function primality(x) returns x when x is prime (or 0 - take care) and the first divisor occurs when x is not prime.
I think you may obtain a better result inlining the primality() function inside the lpf5() function.
I've also tried to insert a table with some primes (from 1 to 383 - the primes in the first 128 results of the indicated formulas) inside the primality function, but the speed difference is unappreciable.
Here the code:
#include <stdio.h>
#include <math.h>
typedef long long unsigned int uint64;
uint64 lpf5(uint64 x);
uint64 primality(uint64 x);
uint64 lpf5(uint64 x)
{
uint64 x_=x;
while ( (x_=primality(x))!=x)
x=x/x_;
return x;
}
uint64 primality(uint64 x)
{
uint64 div=7,f=2,q;
if (x<4 || x==5)
return x;
if (!(x&1))
return 2;
if (!(x%3))
return 3;
if (!(x%5))
return 5;
q=sqrt(x);
while(div<=q) {
if (!(x%div)) {
return div;
}
f=6-f;
div+=f;
}
return x;
}
int main(void) {
uint64 x,k;
do {
printf("Input long int: ");
if (scanf("%llu",&x)<1)
break;
printf("Largest Prime Factor: %llu\n",lpf5(x));
} while(x!=0);
return 0;
}