double power(double base, int exponent){
//Just for context, a double is larger than a long long int
//Also method programmed to assume non-decimal, non-negative input for root
double answer = base;
if(exponent == 0){
return 1.0;
}
else if(exponent > 0){
for(int i=1; i<exponent; i++){
answer*=base;
}
return answer;
}
else{//if exponent is negative
for(int i=1; i<exponent*(-1); i++){
answer*=base;
}
return 1/answer;
}
}
double newtonRaphsonRoot(double base, int root){//FOR FIDING ROOTS OF CONSTANT #s
if(base == 1){
return 1.0;
}
//Formula: x1 = x0 - f(x0)/f'(x0)
//--------------------------------
//Also method programmed to assume non-negative integer input for root
double epsilon=0.01;//accuracy
double answer = base;//answer starts off as initial guess and becomes better approximated each iteration
if(base > 1){
answer=base/2;
}
while( answer - ( power(answer,root) - base)/(root*power(answer,root-1) ) > epsilon){
//Formula: x1 = x0 - f(x0)/f'(x0). Continue formula until error is less than epsilon
answer = answer - ( power(answer,root) - base)/(root*power(answer,root-1) );
std::cout<<"Approximation: answer = "<< answer <<"\n";
}
return answer;
}
There is a mathematical algorithm for calculating the nth root of a number x, known as the Newton-Raphson method for approximating roots. I tried to program this algorithm. Long story short it seems I'm getting the right answer but
Problem 1: I'm stuck in the while and I don't know why
Problem 2: The accuracy was supposed to be determined by variable epsilon, but answer always comes out to 5 places after decimal.*
One problem is that to check for epsilon the code should be
while (fabs(error) > epsilon) {
... improve ...
}
you are instead checking the next approximation against epsilon (also without fabs).
The other problem is that output stream uses a fixed number of decimals when printing floating point values, if you want to increase that you need to look for std::setprecision (or just use printf("%.18g\n", x); that is what I personally prefer to do).
Related
original outdated code:
Write an algorithm that compute the Euler's number until
My professor from Algorithms course gave me the following homework:
Write a C/C++ program that calculates the value of the Euler's number (e) with a given accuracy of eps > 0.
Hint: The number e = 1 + 1/1! +1/2! + ... + 1 / n! + ... = 2.7172 ... can be calculated as the sum of elements of the sequence x_0, x_1, x_2, ..., where x_0 = 1, x_1 = 1+ 1/1 !, x_2 = 1 + 1/1! +1/2 !, ..., the summation continues as long as the condition |x_(i+1) - x_i| >= eps is valid.
As he further explained, eps is the precision of the algorithm. For example, the precision could be 1/100 |x_(i + 1) - x_i| = absolute value of ( x_(i+1) - x_i )
Currently, my program looks in the following way:
#include<iostream>
#include<cstdlib>
#include<math.h>
// Euler's number
using namespace std;
double factorial(double n)
{
double result = 1;
for(double i = 1; i <= n; i++)
{
result = result*i;
}
return result;
}
int main()
{
long double euler = 2;
long double counter = 2;
long double epsilon = 1.0/1000;
long double moduloDifference;
do
{
euler+= 1 / factorial(counter);
counter++;
moduloDifference = (euler + 1 / factorial(counter+1) - euler);
} while(moduloDifference >= epsilon);
printf("%.35Lf ", euler );
return 0;
}
Issues:
It seems my epsilon value does not work properly. It is supposed to control the precision. For example, when I wish precision of 5 digits, I initialize it to 1.0/10000, and it outputs 3 digits before they get truncated after 8 (.7180).
When I use long double data type, and epsilon = 1/10000, my epsilon gets the value 0, and my program runs infinitely. Yet, if change the data type from long double to double, it works. Why epsilon becomes 0 when using long double data type?
How can I optimize the algorithm of finding Euler's number? I know, I can rid off the function and calculate the Euler's value on the fly, but after each attempt to do that, I receive other errors.
One problem with computing Euler's constant this way is pretty simple: you're starting with some fairly large numbers, but since the denominator in each term is N!, the amount added by each successive term shrinks very quickly. Using naive summation, you quickly reach a point where the value you're adding is small enough that it no longer affects the sum.
In the specific case of Euler's constant, since the numbers constantly decrease, one way we can deal with them quite a bit better is to compute and store all the terms, then add them up in reverse order.
Another possibility that's more general is to use Kahan's summation algorithm instead. This keeps track of a running error while it's doing the summation, and takes the current error into account as it's adding each successive term.
For example, I've rewritten your code to use Kahan summation to compute to (approximately) the limit of precision of a typical (80-bit) long double:
#include<iostream>
#include<cstdlib>
#include<math.h>
#include <vector>
#include <iomanip>
#include <limits>
// Euler's number
using namespace std;
long double factorial(long double n)
{
long double result = 1.0L;
for(int i = 1; i <= n; i++)
{
result = result*i;
}
return result;
}
template <class InIt>
typename std::iterator_traits<InIt>::value_type accumulate(InIt begin, InIt end) {
typedef typename std::iterator_traits<InIt>::value_type real;
real sum = real();
real running_error = real();
for ( ; begin != end; ++begin) {
real difference = *begin - running_error;
real temp = sum + difference;
running_error = (temp - sum) - difference;
sum = temp;
}
return sum;
}
int main()
{
std::vector<long double> terms;
long double epsilon = 1e-19;
long double i = 0;
double term;
for (int i=0; (term=1.0L/factorial(i)) >= epsilon; i++)
terms.push_back(term);
int width = std::numeric_limits<long double>::digits10;
std::cout << std::setw(width) << std::setprecision(width) << accumulate(terms.begin(), terms.end()) << "\n";
}
Result: 2.71828182845904522
In fairness, I should actually add that I haven't checked what happens with your code using naive summation--it's possible the problem you're seeing is from some other source. On the other hand, this does fit fairly well with a type of situation where Kahan summation stands at least a reasonable chance of improving results.
#include<iostream>
#include<cmath>
#include<iomanip>
#define EPSILON 1.0/10000000
#define AMOUNT 6
using namespace std;
int main() {
long double e = 2.0, e0;
long double factorial = 1;
int counter = 2;
long double moduloDifference;
do {
e0 = e;
factorial *= counter++;
e += 1.0 / factorial;
moduloDifference = fabs(e - e0);
} while (moduloDifference >= EPSILON);
cout << "Wynik:" << endl;
cout << setprecision(AMOUNT) << e << endl;
return 0;
}
This an optimized version that does not have a separate function to calculate the factorial.
Issue 1: I am still not sure how EPSILON manages the precision.
Issue 2: I do not understand the real difference between long double and double. Regarding my code, why long double requires a decimal point (1.0/someNumber), and double doesn't (1/someNumber)
I have this very simple function that checks the value of (N^N-1)^(N-2):
int main() {
// Declare Variables
double n;
double answer;
// Function
cout << "Please enter a double number >= 3: ";
cin >> n;
answer = pow(n,(n-1)*(n-2));
cout << "n to the n-1) to the n-2 for doubles is " << answer << endl;
}
Based on this formula, it is evident it will reach to infinity, but I am curious until what number/value of n would it hit infinity? Using a loop seems extremely inefficient, but that's all I can think of. Basically, creating a loop that says let n be a number between 1 - 100, iterate until n == inf
Is there a more efficient approach to this problem?
I think you are approaching this the wrong way.
Let : F(N) be the function (N^(N-1))(N-2)
Now you actually know whats the largest number that could be stored in a double type variable
is 0x 7ff0 0000 0000 0000 Double Precision
So now you have F(N) = max_double
just solve for X now.
Does this answer your question?
Two things: the first is that (N^(N-1))^(N-2)) can be written as N^((N-1)*(N-2)). So this would remove one pow call making your code faster.
pow(n, (n-1)*(n-2));
The second is that to know what practical limits you hit, testing all N will literally take a fraction of a second, so there really is no reason to find another practical way.
You could compute it by hand knowing variable size limits and all, but testing it is definitely faster. An example for code (C++11, since I use std::isinf):
#include <iostream>
#include <cmath>
#include <iomanip>
int main() {
double N = 1.0, diff = 10.0;
const unsigned digits = 10;
unsigned counter = digits;
while ( true ) {
double X = std::pow( N, (N-1.0) * (N-2.0) );
if ( std::isinf(X) ) {
--counter;
if ( !counter ) {
std::cout << std::setprecision(digits) << N << "\n";
break;
}
N -= diff;
diff /= 10;
}
N += diff;
}
return 0;
}
This example takes less than a millisecond on my computer, and prints 17.28894235
In my program, I am trying to take the find the largest prime factor of the number 600851475143. I have made one for loop that determines all the factors of that number and stores them in a vector array. The problem I am having is that I don't know how to determine if the factor can be square rooted and give a whole number rather than a decimal. My code so far is:
#include <iostream>
#include <vector>
#include <math.h>
using namespace std;
vector <int> factors;
int main()
{
double num = 600851475143;
for (int i=1; i<=num; i++)
{
if (fmod(num,i)==0)
{
factors.push_back(i);
}
}
for (int i=0; i<factors.size(); i++)
{
if (sqrt(factor[i])) // ???
}
}
Can someone show me how to determine whether a number can be square rooted or not through my if statement?
int s = sqrt(factor[i]);
if ((s * s) == factor[i])
As hobbs pointed out in the comments,
Assuming that double is the usual 64-bit IEEE-754 double-precision float, for values less than 2^53 the difference between one double and the next representable double is less than or equal to 1. Above 2^53, the precision is worse than integer.
So if your int is 32 bits you are safe. If you have to deal with numbers bigger than 2^53, you may have some precision errors.
Perfect squares can only end in 0, 1, 4, or 9 in base 16, So for 75% of your inputs (assuming they are uniformly distributed) you can avoid a call to the square root in exchange for some very fast bit twiddling.
int isPerfectSquare(int n)
{
int h = n & 0xF; // h is the last hex "digit"
if (h > 9)
return 0;
// Use lazy evaluation to jump out of the if statement as soon as possible
if (h != 2 && h != 3 && h != 5 && h != 6 && h != 7 && h != 8)
{
int t = (int) floor( sqrt((double) n) + 0.5 );
return t*t == n;
}
return 0;
}
usage:
for ( int i = 0; i < factors.size(); i++) {
if ( isPerfectSquare( factor[ i]))
//...
}
Fastest way to determine if an integer's square root is an integer
The following should work. It takes advantage of integer truncation.
if (int (sqrt(factor[i])) * int (sqrt(factor[i])) == factor[i])
It works because the square root of a non-square number is a decimal. By converting to an integer, you remove the fractional part of the double. Once you square this, it is no longer equal to the original square root.
You also have to take into account the round-off error when comparing to cero. You can use std::round if your compiler supports c++11, if not, you can do it yourself (here)
#include <iostream>
#include <vector>
#include <math.h>
using namespace std;
vector <int> factors;
int main()
{
double num = 600851475143;
for (int i=1; i<=num; i++)
{
if (round(fmod(num,i))==0)
{
factors.push_back(i);
}
}
for (int i=0; i<factors.size(); i++)
{
int s = sqrt(factor[i]);
if ((s * s) == factor[i])
}
}
You are asking the wrong question. Your algorithm is wrong. (Well, not entirely, but if it were to be corrected following the presented idea, it would be quite inefficient.) With your approach, you need also to check for cubes, fifth powers and all other prime powers, recursively. Try to find all factors of 5120=5*2^10 for example.
The much easier way is to remove a factor after it was found by dividing
num=num/i
and only increase i if it is no longer a factor. Then, if the iteration encounters some i=j^2 or i=j^3,... , all factors j, if any, were already removed at an earlier stage, when i had the value j, and accounted for in the factor array.
You could also have mentioned that this is from the Euler project, problem 3. Then you would have, possibly, found the recent discussion "advice on how to make my algorithm faster" where more efficient variants of the factorization algorithm were discussed.
Here is a simple C++ function I wrote for determining whether a number has an integer square root or not:
bool has_sqrtroot(int n)
{
double sqrtroot=sqrt(n);
double flr=floor(sqrtroot);
if(abs(sqrtroot - flr) <= 1e-9)
return true;
return false;
}
As sqrt() function works with floating-point it is better to avoid working with its return value (floating-point calculation occasionally gives the wrong result, because of precision error). Rather you can write a function- isSquareNumber(int n), which will decide if the number is a square number or not and the whole calculation will be done in integer.
bool isSquareNumber(int n){
int l=1, h=n;
while(l<=h){
int m = (l+h) / 2;
if(m*m == n){
return true;
}else if(m*m > n){
h = m-1;
}else{
l = m+1;
}
}
return false;
}
int main()
{
// ......
for (int i=0; i<factors.size(); i++){
if (isSquareNumber(factor[i]) == true){
/// code
}
}
}
What this code does now: I give int values and it calculates the average between them.
What Ive spent hours on trying to get it do: Ive tried making it so that it would calculate the average between double values. Ive tried everything but it always fails or goes into an infinite loop or will not compile.
Question: So how should I modify my code to make it work with double values/numbers?
#include <stdio.h>
void main()
{
int Tau[10]={0,0,0,0,0,0,0,0,0,0};
int r, i = 0;
int m = 0;
int huku = 0;
do{
printf("Enter numbers: ");
scanf_s("%d", &i);
Tau[m]+=i;
huku++;
}while(i != 0);
r = (Tau[m]/(huku-1));
printf("The average of your numbers is; %d\n", r);
}
You have some issues in your code but basically, integer division will not give you doubles. The result of an integer divided by an integer is another integer, not a double. If you want doubles you need to cast either the numerator or denominator to a double and store the result in a double.
Welcome to Numerical Analysis 1001.
Integer math:
2 / 3 = 0;
4 / 2 = 2;
5 / 2 = 2;
Integers don't do fractions.
I don't see why you need Tau to be a vector in your case. An int would suffice.
huku-1 -> That is wrong. It should be just huku.
You need to cast Tau and huku to double when you divide. It won't hurt to check that huku is != 0 also.
m is useless. Just delete it.
r shouldn't be an int if you wish to store Tau/huku in it.
in printf replace %d with %lf
The simplest changes only involve four lines:
double Tau[10] = {0,0,0,0,0,0,0,0,0,0};
double r, i = 0;
scanf_s("%f", &i);
printf("The average of your numbers is; %f\n", r);
Note that this doesn't address the coding issues; all it does is change the code to read and work with double instead of int.
double r = 0;
int i = 0;
r = ((double)Tau[m]/((double)huku-1));
printf("The average of your numbers is; %f\n", r);
// Question is tagged for C++, but the code is in C.
// I will change your code a bit, because you had quite a few mistakes.
#include <stdio.h>
void main ()
{
int sum = 0; // sum of all numbers you entered, to find average you only need total sum and number of entries
int numOfEntries; // number of entries (numbers taken from input)
int inputNum; // variable where you will write numbers from input one by one
double average; // Not really needed, but it can help to simplify the problem to you.
printf("Enter numbers: ");
do
{
scanf_s("%d", &inputNum);
sum += inputNum;
numOfEntries++;
} while (inputNum != 0); // I understand you read numbers until you read value 0.
// int / int will give you rounded number, not the true average, so we need to convert one of the operands to a real number, in this case double
// double / int or int / double will give you a real number as result, which will have true average value, and that is why I converted sum to a real number
if (numOfEntries != 0)
average = (double)sum / numOfEntries;
else
average = 0;
printf("The average of your numbers is; %f\n", average); // Here I did it again - print double instead of int to get true value.
}
It will be even easier to change this:
....
double sum = 0;
...
average = sum / numOfEntries; // Here sum is already double, not int, so you don't need to change it manually.
...
Now, if you want to make it work for double, the only difference will be:
double sum = 0;
double inputNum;
scanf_s("%lf", &inputNum);
average = sum / numOfEntries;
So, to round up the story - you have variable to input a number from keyboard, a variable which holds sum of all entered numbers so far, a variable which counts how many numbers you entered from keyboard. You input numbers until you enter 0 as value, then the program will exit the loop. Formula for average number is sum of all divided by number of numbers. With integers you have to add conversion to a real number or otherways you won't get accurate result.
I hope I didn't confuse you. :D
Below is a simple program which computes sqrt of a number using Bisection. While executing this with a call like sqrtr(4,1,4) in goes into an endless recursion . I am unable to figure out why this is happening. Below is the function :
double sqrtr(double N , double Low ,double High )
{
double value = 0.00;
double mid = (Low + High + 1)/2;
if(Low == High)
{
value = High;
}
else if (N < mid * mid )
{
value = sqrtr(N,Low,mid-1) ;
}
else if(N >= mid * mid)
{
value = sqrtr(N,mid,High) ;
}
return value;
}
You may have to put a range on your low == high comparison, i.e. high - low < .000001 for six decimal places of precision.
Apart from having a bad termination condition, how did you get this:
else if (N < mid * mid )
{
value = sqrtr(N,Low,mid-1) ;
How is the mid-1 justified? Didn't you cut-and-paste some code for integer binary search?
It's rarely a good idea to rely on floating point values equaling one another. It's very easy for them to be off by a slight amount since, unlike integers, they can't represent all values in the range of values that they represent.
So, you'll likely need to do a comparison to a given precision rather than exact equality.
As pointed out in one of the comments above, you should look at the paper "What Every Computer Scientist Should Know About Floating-Point Arithmetic". It's a classic, excellent paper on the nature of floating point numbers.
There are several problems. As noted by jpalecek, it looks as though you've cut-and-pasted a (not very good) binary search routine for an indexed array without understanding how it works. Also, the termination criterion is overly strict.
I suppose this is a learning exercise, because bisection and recursion is a very poor way to solve for sqrt().
The code below works, but it is horribly slow and inaccurate.
#include <iostream>
using namespace std;
double sqrtr(double N , double Low ,double High )
{
// Precondition: Low and High, Low <= High, must be non-negative, and must
// bracket sqrt(N).
const double sqrt_mef = 1e-8; // Approximate square root of machine efficiency
double mid = (Low + High)/2; // No +1
if((High-Low)/(1+mid) < sqrt_mef)
{
return mid;
}
else if (N < mid * mid )
{
return sqrtr(N,Low,mid) ; // No -1
}
else
{
return sqrtr(N,mid,High) ;
}
}
int main()
{
double sqrt_2 = sqrtr(2.0, 0, 2.0);
cout << sqrt_2*sqrt_2 << endl;
getchar();
}