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)
Related
I have a vector of numbers (floats), representing everything after the second of some time stamp. They have varying lengths. It looks something like this:
4456
485926
346
...
Representing 0.4456, 0.485926, and 0.346 seconds, respectively. I need to convert each of these to milliseconds, however I can’t simply multiply each by some constant since they’re all of different lengths. I’m fine with loosing accuracy, I just need the first 3 digits (the millisecond bit). How can this be done?
Try this:
#include <iostream>
#include <string>
using namespace std;
int getFirstThreeDigits(int number){
return stoi(to_string(number).substr(0,3));
}
int main()
{
float values[] = {4456, 485926, 346};
int arrLength = (sizeof(values)/sizeof(*values));
for( int i = 0 ; i < arrLength ; i++){
cout << getFirstThreeDigits(values[i]) << endl;
}
}
I'm assuming here that the integral portion of the float represents a subsecond value, so that 1234f is actually 0.1234 seconds. That seems to be what your question states.
If that's the case, it seems to me you can just continuously divide the value by ten until you get something less than one. Then multiply it by one thousand and round. That would go something like:
#include <iostream>
int millis(float value) {
if (value < 0) return -millis(-value);
//while (value >= 1000f) value /= 1000f;
while (value >= 1.0f) value /= 10.f;
return static_cast<int>(value * 1000 + .5f);
}
int main(int argc, char *argv[]) {
for (int i = 1; i < argc; ++i) {
float f= atof(argv[i]);
std::cout << " " << f << " -> " << millis(f) << "\n";
}
}
I've also put in a special case to handle negative number and a (commented-out, optional) optimisation to more quickly get down to sub-one for larger numbers.
A transcript follows with your example values:
pax> ./testprog 4456 485926 346
4456 -> 446
485926 -> 486
346 -> 346
If instead the values are already sub-second floats and you just want the number of milli-seconds, you do the same thing but without the initial divisions:
int millis(float value) {
if (value < 0) return -millis(-value);
return static_cast<int>(value * 1000 + .5f);
}
Using "(int)log10 + 1" is an easy way to get the number of integer digits
auto x = 485926;
auto len = (int)std::log10(x) + 1;
https://godbolt.org/z/v1jz7P
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.
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've written a few programs to find pi, this one being the most advanced. I used Machin's formula, pi/4 = 4(arc-tan(1/5)) - (arc-tan(1/239)).
The problem is that however many iterations I do, I get the same result, and I can't seem to understand why.
#include "stdafx.h"
#include <iostream>
#include <iomanip>
#include <math.h>
using namespace std;
double arctan_series(int x, double y) // x is the # of iterations while y is the number
{
double pi = y;
double temp_Pi;
for (int i = 1, j = 3; i < x; i++, j += 2)
{
temp_Pi = pow(y, j) / j; //the actual value of the iteration
if (i % 2 != 0) // for every odd iteration that subtracts
{
pi -= temp_Pi;
}
else // for every even iteration that adds
{
pi += temp_Pi;
}
}
pi = pi * 4;
return pi;
}
double calculations(int x) // x is the # of iterations
{
double value_1, value_2, answer;
value_1 = arctan_series(x, 0.2);
value_2 = arctan_series(x, 1.0 / 239.0);
answer = (4 * value_1) - (value_2);
return answer;
}
int main()
{
double pi;
int iteration_num;
cout << "Enter the number of iterations: ";
cin >> iteration_num;
pi = calculations(iteration_num);
cout << "Pi has the value of: " << setprecision(100) << fixed << pi << endl;
return 0;
}
I have not been able to reproduce your issue, but here is a bit cleaned up code with a few C++11 idioms and better variable names.
#include <iostream>
#include <iomanip>
#include <math.h>
using namespace std;
// double arctan_series(int x, double y) // x is the # of iterations while y is the number
// then why not name the parameters accoringly? In math we usually use x for the parameter.
// prefer C++11 and the auto notation wherever possible
auto arctan_series(int iterations, double x) -> double
{
// note, that we don't need any temporaries here.
// note, that this loop will never run, when iterations = 1
// is that really what was intended?
for (int i = 1, j = 3; i < iterations; i++, j += 2)
{
// declare variables as late as possible and always initialize them
auto t = pow(x, j) / j;
// in such simple cases I prefer ?: over if-else. Your milage may vary
x += (i % 2 != 0) ? -t : t;
}
return x * 4;
}
// double calculations(int x) // x is the # of iterations
// then why not name the parameter accordingly
// BTW rename the function to what it is supposed to do
auto approximate_pi(int iterations) -> double
{
// we don't need all of these temporaries. Just write one expression.
return 4 * arctan_series(iterations, 0.2) - arctan_series(iterations, 1.0 / 239.0);
}
auto main(int, char**) -> int
{
cout << "Enter the number of iterations: ";
// in C++ you should declare variables as late as possible
// and always initialize them.
int iteration_num = 0;
cin >> iteration_num;
cout << "Pi has the value of: "
<< setprecision(100) << fixed
<< approximate_pi(iteration_num) << endl;
return 0;
}
When you remove my explanatory comments, you'll see, that the resulting code is a lot more concise, easier to read, and therefore easier to maintain.
I tried a bit:
Enter the number of iterations: 3
Pi has the value of: 3.1416210293250346197169164952356368303298950195312500000000000000000000000000000000000000000000000000
Enter the number of iterations: 2
Pi has the value of: 3.1405970293260603298790556436870247125625610351562500000000000000000000000000000000000000000000000000
Enter the number of iterations: 7
Pi has the value of: 3.1415926536235549981768144789384678006172180175781250000000000000000000000000000000000000000000000000
Enter the number of iterations: 42
Pi has the value of: 3.1415926535897940041763831686694175004959106445312500000000000000000000000000000000000000000000000000
As you see, I obviously get different results for different numbers of iterations.
That method converges very quickly. You'll get more accuracy if you start with the smallest numbers first. Since 5^23 > 2^53 (the number of bits in the mantissa of a double), probably the maximum number of iterations is 12 (13 won't make any difference). You'll get more accuracy starting with the smaller numbers. The changed lines have comments:
double arctan_series(int x, double y)
{
double pi = y;
double temp_Pi;
for (int i = 1, j = x*2-1; i < x; i++, j -= 2) // changed this line
{
temp_Pi = pow(y, j) / j;
if ((j & 2) != 0) // changed this line
{
pi -= temp_Pi;
}
else
{
pi += temp_Pi;
}
}
pi = pi * 4;
return pi;
}
For doubles, there is no point in setting precision > 18.
If you want an alternative formula that takes more iterations to converge, use pi/4 = arc-tan(1/2) + arc-tan(1/3), which will take about 24 iterations.
This is another way if some of you are interested. The loop calculates the integral of the function : sqrt(1-x²)
Which represents a semicircle of radius 1. Then we multiply by two the area. Finally we got the surface of the circle which is PI.
#include <iomanip>
#include <cmath>
#define f(x) sqrt(1-pow(x,2))
double integral(int a, int b, int p)
{
double d=pow(10, -p), s=0;
for (double x=a ; x+d<=b ; x+=d)
{
s+=f(x)+f(x+d);
}
s*=d/2.0;
return s;
}
int main()
{
cout << "PI=" << setprecision (9) << 2.0*integral(-1,1,6) << endl;
}