How can I compute the square root of 3 in C++ using the following relation?
Here is what I tried:
#include <iostream>
#include <cmath>
int main(void)
{
double prevRes(1);
double res(1 + 1./2);
short i(2);
while (abs(prevRes - res) > 1.e-14)
{
prevRes = res;
res = i + 1 / res;
i = 3 - i;
}
std::cout << res << std::endl;
return 0;
}
The program runs forever.
It's a shame that this question wasn't asked with more effort and detail so that it was taken seriously. I've always been confused by the appearance and concept of continued fractions, but it's been nice taking the time to think about them and implement one.
This particular one can be done iteratively. As #wally states, the continued fraction shown in the question does not converge to sqrt(3), but to ~1.36603. The two top-most coefficients should be 1. Notice that sqrt(3) ~= 1 + (1/1.36603), and that all the coefficients in the continued fraction alternate.
So, if a loop works from the bottom up until the alternating continued fraction converges then one more calculation after the loop will give us the correct answer. At each iteration the reciprocal of the current value is added to either 1 or 2. The initial value can be anything.
#include <iostream>
#include <cmath>
#include <limits>
// Calculate square root of 3 with a continued fraction
int main(void) {
int iterations = 0;
double epsilon = 1.0e-12; //error bounds
double prev = 0.0;
double curr = 1.0; //initial estimate
double error = curr - prev;
// Don't show more precision than we have
std::cout.precision(std::numeric_limits<double>::digits10);
// Iterate the continued fraction [1;1,2,1,2...]
// from the bottom up until it converges with errors
// less than epsilon.
while (std::abs(error) > epsilon) {
prev = curr;
// Unroll the loop with the repeating pattern here
curr = 2 + (1/curr);
curr = 1 + (1/curr);
iterations++;
error = curr - prev;
std::cout << "error at iteration " << iterations
<< " was " << error << std::endl;
}
// The actual continued fraction we want to evaluate
// is [1;1,1,2,1,2,...].
// The two top-level coefficients are 1, so do
// another half iteration here.
curr = 1 + (1/curr);
std::cout << "sqrt(3) = " << curr << " after "
<< iterations << " iterations" << std::endl;
return 0;
}
This strategy should work for any continued fraction with that ends in a repeating pattern of coefficients.
As for why the original code does not complete, I'll leave that to the author to figure out. Print statements or a pocket calculator will help.
The formula seems a bit wrong if I compare it to wikipedia. Note the 1 + is repeated at the start.
Next we can use a recursive function to perform the calculation and provide a number of iterations. Note that we can use a large return value to terminate the recursion (or even zero, but that would require more iterations as it is technically making the wrong assumption).
Finally we keep trying more iterations until the error is small enough.
#include <iostream>
#include <limits>
#include <cmath>
double f(int depth, bool odd = true)
{
if(depth == 0)
return std::numeric_limits<double>::max();
return (odd ? 1 : 2) + 1. / f(--depth, !odd);
}
double sqrt3(int depth = 10)
{
return 1 + 1. / f(depth);
}
int main(void)
{
int depth{2};
double prevRes{sqrt3(depth)};
double res{sqrt3(++depth)};
while(abs(prevRes - res) > 1.e-14)
{
prevRes = res;
res = sqrt3(++depth);
}
std::cout << "Answer is " << res << " at depth " << depth << ".\n";
}
Output:
Answer is 1.73205 at depth 26.
Use the built in sqrt function.
#include <cstdio>
#include <cmath>
int main ()
{
double param, result;
param = 1024.0;
result = sqrt (param);
printf ("sqrt(%f) = %f\n", param, result );
return 0;
}
double sqrt_of_three(bool adds_two, int rec_depth, int max_rec_depth)
{
int x;
if (rec_depth < 2)
x = 1;
else
x = adds_two ? 2 : 1;
if (rec_depth < max_rec_depth)
return x + 1/sqrt_of_three(!adds_two, ++rec_depth, max_rec_depth);
return x;
}
And this method can be called with an estimate for a threshold.
int main()
{
std::cout << sqrt_of_three(true, 0, 10);
}
This is an example how to recursively call a function that calculates the square root of 3. Now you can either manually set the maximum recursion depth by trial and error or you do something that you did with your first approach and check after each complete recursion if the value between two different maximum recursion depths is smaller than some threshold.
It's for sure not the most efficient way to find the square root of three because you have to do n*(n-1)/2 (where n is the recursion depth that satisfied the boundary that you set) recursions in total and depending on how close you want to converge to the real result this can be a lot.
Related
I have a range of base-10 logarithmically spaced points and I need to calculate the #points-per-decade for the points.
Based on this section from wikipedia we have #decades = log10(start / stop). From this we should be able to calculate #points-per-decade as #points / #decades. However this does not give the right answer. Here is a short program I've been using to test this method:
#include <iostream>
#include <algorithm>
#include <vector>
#include <cmath>
#include <float.h>
class GenLog {
public:
GenLog(double start, double step) : curVal(start), step(step) {
m = 1.0 / step;
b = std::log10(start);
stepi = 0;
};
double operator()() {
++stepi;
double arg = m*stepi+b;
if (arg < DBL_MAX_10_EXP) {
curVal += pow(10.0, arg) - curVal;
} else {
curVal = DBL_MAX;
}
return curVal;
}
private:
double step, stepi, curVal, m, b;
};
int main(int argc, char *argv[])
{
if (argc < 5) {
std::cout << "Wrong number of args: format is [start] [stop] [points-per-decade] [size]\n";
return -1;
}
double start = atof(argv[1]);
double stop = atof(argv[2]);
double ppd = atof(argv[3]);
int size = atoi(argv[4]);
std::vector<double> vals;
vals.push_back(start);
// generate total number of points - 2 (excluding endpoints, GenLog takes in
// starting freq, and #point/dec
std::generate_n(std::back_inserter(vals), size - 2, GenLog(start, ppd));
vals.push_back(stop);
for (auto i : vals) {
std::cout << i << " ";
}
std::cout << "\n---TEST BACKWARDS PPD---\n";
std::cout << "ppd: " << ppd << "\t " << (vals.size()) / std::log10(*std::prev(vals.end()) / vals.front()) << "\n";
return 0;
}
Example output:
This generates a logarithmically spaced series of points from 1 to 10.1681 with 13 points per decade for a total of 15 points--although in principal you only need the starting point, and the points per decade to generate the next logarithmic point in the series.
As you can see the resulting numbers (13 and 14.8922) are not the same when they should be.
./so 1.0 10.1681 13 15
1 1.19378 1.4251 1.70125 2.03092 2.42446 2.89427 3.45511 4.12463 4.92388 5.87802 7.01704 8.37678 10 10.1681
---TEST BACKWARDS PPD---
ppd: 13 14.8922
based on my testing so far I do not think it is anything like an off-by-one error. Perhaps the calculations for #points-per-decade is conceptually incorrect? If so what is the correct way of calculating it?
My way of calculating #points-per-decade was incorrect
So based on the last equation in the calculations section of the wikipedia article we have:
step-size = 10^(1 / #points-per-decade)
since we know the step-size we can re-arrange to
1/#points-per-decade * ln(10)=ln(step-size)
and finally solve for #points-per-decade
#points-per-decade = ln(10) / ln(step-size)
Can you give me advice about precision of computing Taylor series for an exponent? We have a degree of exponent and a figure of precision calculating as imput data. We should recieve a calculating number with a given precision as output data. I wrote a program, but when I calculate an answer and compare it with embedded function's answer, it has differents. Can you advice me, how I can destroy a difference between answeres? formula of exponent's calculating
#include "stdafx.h"
#include "iostream"
#include <math.h>
#include <Windows.h>
#include <stdlib.h>
using namespace std;
int Factorial(int n);
double Taylor(double x, int q);
int main()
{
double res = 0;
int q = 0;
double number = 0;
cout << "Enter positive number" << "\n";
cin >> number;
cout << "Enter rounding error (precision)" << "\n";
cin >> q;
cout << "\n" << "\n";
res = Taylor(number, q);
cout << "Answer by Taylor : " << res;
cout << "Answer by embedded function: " << exp(number);
Sleep(25000);
return 0;
}
int Factorial(int n) {
int res = 1;
int i = 2;
if (n == 1 || n == 0)
return 1;
else
{
while (i <= n)
{
res *= i;
i++;
}
return res;
}
}
double Taylor(double x, int q) {
double res = 1;
double res1 = 0;
int i =1;
while (i)
{
res += (pow(x, i) / Factorial(i));
if (int(res*pow(10, q)) < (res*pow(10, q)))
{//rounding res below
if ( ( int (res * pow(10,q+1)) - int(res*pow(10, q))) <5 )
res1 = (int(res*pow(10, q))) * pow(10, (-q));
else
res1 = (int(res*pow(10, q))) * pow(10, (-q)) + pow(10,-q);
return res1;
}
i++;
}
}
There are two problems in your code. First, the factorial is very prone to overflow. Actually I dont know when overflow occurs for int factorials, but I remember that eg on usual pocket calculators x! overflows already for x==70. You probably dont need that high factorials, but still it is better to avoid that problem right from the start. If you look at the correction that needs to be added in each step: x^i / i! (maths notation) then you notice that this value is actually much smaller than x^i or i! respectively. Also you can calculate the value easily from the previous one by simply multiplying it by x/i.
Second, I dont understand your calculations for the precision. Maybe it is correct, but to be honest for me it looks too complicated to even try to understand it ;).
Here is how you can get the correct value:
#include <iostream>
#include <cmath>
struct taylor_result {
int iterations;
double value;
taylor_result() : iterations(0),value(0) {}
};
taylor_result taylor(double x,double eps = 1e-8){
taylor_result res;
double accu = 1; // calculate only the correction
// but not its individual terms
while(accu > eps){
res.value += accu;
res.iterations++;
accu *= (x / (res.iterations));
}
return res;
}
int main() {
std::cout << taylor(3.0).value << "\n";
std::cout << exp(3.0) << "\n";
}
Note that I used a struct to return the result, as you should pay attention to the number of iterations needed.
PS: see here for a modified code that lets you use a already calculated result to continue the series for better precision. Imho a nice solution should also provide a way to set a limit for the number of iterations, but this I leave for you to implement ;)
My task is to ask the user to how many decimal places of accuracy they want the summation to iterate compared to the actual value of pi. So 2 decimal places would stop when the loop reaches 3.14. I have a complete program, but I am unsure if it actually works as intended. I have checked for 0 and 1 decimal places with a calculator and they seem to work, but I don't want to assume it works for all of them. Also my code may be a little clumsy since were are still learning the basics. We only just learned loops and nested loops. If there are any obvious mistakes or parts that could be cleaned up, I would appreciate any input.
Edit: I only needed to have this work for up to five decimal places. That is why my value of pi was not precise. Sorry for the misunderstanding.
#include <iostream>
#include <cmath>
using namespace std;
int main() {
const double PI = 3.141592;
int n, sign = 1;
double sum = 0,test,m;
cout << "This program determines how many iterations of the infinite series for\n"
"pi is needed to get with 'n' decimal places of the true value of pi.\n"
"How many decimal places of accuracy should there be?" << endl;
cin >> n;
double p = PI * pow(10.0, n);
p = static_cast<double>(static_cast<int>(p) / pow(10, n));
int counter = 0;
bool stop = false;
for (double i = 1;!stop;i = i+2) {
sum = sum + (1.0/ i) * sign;
sign = -sign;
counter++;
test = (4 * sum) * pow(10.0,n);
test = static_cast<double>(static_cast<int>(test) / pow(10, n));
if (test == p)
stop = true;
}
cout << "The series was iterated " << counter<< " times and reached the value of pi\nwithin "<< n << " decimal places." << endl;
return 0;
}
One of the problems of the Leibniz summation is that it has an extremely low convergence rate, as it exhibits sublinear convergence. In your program you also compare a calculated extimation of π with a given value (a 6 digits approximation), while the point of the summation should be to find out the right figures.
You can slightly modify your code to make it terminate the calculation if the wanted digit doesn't change between iterations (I also added a max number of iterations check). Remember that you are using doubles not unlimited precision numbers and sooner or later rounding errors will affect the calculation. As a matter of fact, the real limitation of this code is the number of iterations it takes (2,428,700,925 to obtain 3.141592653).
#include <iostream>
#include <cmath>
#include <iomanip>
using std::cout;
// this will take a long long time...
const unsigned long long int MAX_ITER = 100000000000;
int main() {
int n;
cout << "This program determines how many iterations of the infinite series for\n"
"pi is needed to get with 'n' decimal places of the true value of pi.\n"
"How many decimal places of accuracy should there be?\n";
std::cin >> n;
// precalculate some values
double factor = pow(10.0,n);
double inv_factor = 1.0 / factor;
double quad_factor = 4.0 * factor;
long long int test = 0, old_test = 0, sign = 1;
unsigned long long int count = 0;
double sum = 0;
for ( long long int i = 1; count < MAX_ITER; i += 2 ) {
sum += 1.0 / (i * sign);
sign = -sign;
old_test = test;
test = static_cast<long long int>(sum * quad_factor);
++count;
// perform the test on integer values
if ( test == old_test ) {
cout << "Reached the value of Pi within "<< n << " decimal places.\n";
break;
}
}
double pi_leibniz = static_cast<double>(inv_factor * test);
cout << "Pi = " << std::setprecision(n+1) << pi_leibniz << '\n';
cout << "The series was iterated " << count << " times\n";
return 0;
}
I have summarized the results of several runs in this table:
digits Pi iterations
---------------------------------------
0 3 8
1 3.1 26
2 3.14 628
3 3.141 2,455
4 3.1415 136,121
5 3.14159 376,848
6 3.141592 2,886,751
7 3.1415926 21,547,007
8 3.14159265 278,609,764
9 3.141592653 2,428,700,925
10 3.1415926535 87,312,058,383
Your program will never terminate, because test==p will never be true. This is a comparison between two double-precision numbers that are calculated differently. Due to round-off errors, they will not be identical, even if you run an infinite number of iterations, and your math is correct (and right now it isn't, because the value of PI in your program is not accurate).
To help you figure out what's going on, print the value of test in each iteration, as well as the distance between test and pi, as follows:
#include<iostream>
using namespace std;
void main() {
double pi = atan(1.0) * 4; // Make sure you have a precise value of PI
double sign = 1.0, sum = 0.0;
for (int i = 1; i < 1000; i += 2) {
sum = sum + (1.0 / i) * sign;
sign = -sign;
double test = 4 * sum;
cout << test << " " << fabs(test - pi) << "\n";
}
}
After you make sure the program works well, change the stopping condition eventually to be based on the distance between test and pi.
for (int i=1; fabs(test-pi)>epsilon; i+=2)
I'm working on this program that approximates a taylor series function. I have to approximate it so that the taylor series function stops approximating the sin function with a precision of .00001. In other words,the absolute value of the last approximation minus the current approximation equals less than or equal to 0.00001. It also approximates each angle from 0 to 360 degrees in 15 degree increments. My logic seems to be correct, but I cannot figure out why i am getting garbage values. Any help is appreciated!
#include <math.h>
#include <iomanip>
#include <iostream>
#include <string>
#include <stdlib.h>
#include <cmath>
double fact(int x){
int F = 1;
for(int i = 1; i <= x; i++){
F*=i;
}
return F;
}
double degreesToRadians(double angle_in_degrees){
double rad = (angle_in_degrees*M_PI)/180;
return rad;
}
using namespace std;
double mySine(double x){
int current =99999;
double comSin=x;
double prev=0;
int counter1 = 3;
int counter2 = 1;
while(current>0.00001){
prev = comSin;
if((counter2 % 2) == 0){
comSin += (pow(x,(counter1))/(fact(counter1)));
}else{
comSin -= (pow(x,(counter1))/(fact(counter1)));
}
current=abs(prev-comSin);
cout<<current<<endl;
counter1+=2;
counter2+=1;
}
return comSin;
}
using namespace std;
int main(){
cout<<"Angle\tSine"<<endl;
for (int i = 0; i<=360; i+=15){
cout<<i<<"\t"<<mySine(degreesToRadians(i));
}
}
Here is an example which illustrates how to go about doing this.
Using the pow function and calculating the factorial at each iteration is very inefficient -- these can often be maintained as running values which are updated alongside the sum during each iteration.
In this case, each iteration's addend is the product of two factors: a power of x and a (reciprocal) factorial. To get from one iteration's power factor to the next iteration's, just multiply by x*x. To get from one iteration's factorial factor to the next iteration's, just multiply by ((2*n+1) + 1) * ((2*n+1) + 2), before incrementing n (the iteration number).
And because these two factors are updated multiplicatively, they do not need to exist as separate running values, they can exists as a single running product. This also helps avoid precision problems -- both the power factor and the factorial can become large very quickly, but the ratio of their values goes to zero relatively gradually and is well-behaved as a running value.
So this example maintains these running values, updated at each iteration:
"sum" (of course)
"prod", the ratio: pow(x, 2n+1) / factorial 2n+1
"tnp1", the value of 2*n+1 (used in the factorial update)
The running update value, "prod" is negated every iteration in order to to factor in the (-1)^n.
I also included the function "XlatedSine". When x is too far away from zero, the sum requires more iterations for an accurate result, which takes longer to run and also can require more precision than our floating-point values can provide. When the magnitude of x goes beyond PI, "XlatedSine" finds another x, close to zero, with an equivalent value for sin(x), then uses this shifted x in a call to MaclaurinSine.
#include <iostream>
#include <iomanip>
// Importing cmath seemed wrong LOL, so define Abs and PI
static double Abs(double x) { return x < 0 ? -x : x; }
const double PI = 3.14159265358979323846;
// Taylor series about x==0 for sin(x):
//
// Sum(n=[0...oo]) { ((-1)^n) * (x^(2*n+1)) / (2*n + 1)! }
//
double MaclaurinSine(double x) {
const double xsq = x*x; // cached constant x squared
int tnp1 = 3; // 2*n+1 | n==1
double prod = xsq*x / 6; // pow(x, 2*n+1) / (2*n+1)! | n==1
double sum = x; // sum after n==0
for(;;) {
prod = -prod;
sum += prod;
static const double MinUpdate = 0.00001; // try zero -- the factorial will always dominate the power of x, eventually
if(Abs(prod) <= MinUpdate) {
return sum;
}
// Update the two factors in prod
prod *= xsq; // add 2 to the power factor's exponent
prod /= (tnp1 + 1) * (tnp1 + 2); // update the factorial factor by two iterations
tnp1 += 2;
}
}
// XlatedSine translates x to an angle close to zero which will produce the equivalent result.
double XlatedSine(double x) {
if(Abs(x) >= PI) {
// Use int casting to do an fmod PI (but symmetric about zero).
// Keep in mind that a really big x could overflow the int,
// however such a large double value will have lost so much precision
// at a sub-PI-sized scale that doing this in a legit fashion
// would also disappoint.
const int p = static_cast<int>(x / PI);
x -= PI * p;
if(p % 2) {
x = -x;
}
}
return MaclaurinSine(x);
}
double DegreesToRadians(double angle_deg) {
return PI / 180 * angle_deg;
}
int main() {
std::cout<<"Angle\tSine\n" << std::setprecision(12);
for(int i = 0; i<=360; i+=15) {
std::cout << i << "\t" << MaclaurinSine(DegreesToRadians(i)) << "\n";
//std::cout << i << "\t" << XlatedSine(DegreesToRadians(i)) << "\n";
}
}
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