I need solve this operation in a while loop. The N,X, and Z are integers given by the user.
I tried this, but it does not show me the real results.
while (i <= n) {
double r = 1, p = 1;
p = x / n + z;
p = p * p;
cout << "Resultado: " <<p<< endl;
i++;
}
Your code at least has three issues:
You're re-declaring and re-initializing p every loop iteration, losing the previous value.
You're setting p to x/n+z every iteration, losing the previous value.
Your x/n+z executes the division before the addition.
You're continuously "resetting" p's value here:
while(i <= n)
{
// ...
// `p` is getting re-initialized to 1 here:
// (losing the previous value)
double r=1, p=1;
// `p` is being set to `x/n+z` here:
// (losing the previous value)
p = x/n+z;
p = p*p;
// ...
}
Make a temporary variable instead, and move p's declaration outside the loop:
double p = 1;
while(i <= n)
{
// ...
double temp = x/n+z;
p = p * temp;
// ...
}
Also, as noted by Daniel S., you require parenthesis around n+z:
double temp0 = x/n+z;
// Evaluates to (x/n)+z.
double temp1 = x/(n+z);
// Evaluates to x/(n+z). (Which is what you want.)
This happens because the / division operator has higher precedence than the + addition operator. Learn about operator precedence here.
Some C++ syntaxe mistake and a good math error
int i=1; // don't forget the initialization of i
double p = 1/2; // p will be your result, stored outside of the while so we keep memory
while(i<=n) // you want to loop from 1 to n included
{
// we don't need r
p = p * x / (n + z); // you forgot the parenthesis here, without them you are doing (x / n) + z;
}
So at start p = 1/2 which is the left part of your equation
then at each loop we multiply the current value of p by the factor x / (n + z).
As this factor doesn't change from one loop to an other you could also store it somewhere.
This should be working.
double s;
double p = 1;
int n, x, z;
int i = 1;
while (i <= n)
{
p = p*(x / (n + z));
i++;
}
s = 1 / 2 * p;
Related
I've been trying to write a function to approximate an the value of an integral using the Composite Simpson's Rule.
template <typename func_type>
double simp_rule(double a, double b, int n, func_type f){
int i = 1; double area = 0;
double n2 = n;
double h = (b-a)/(n2-1), x=a;
while(i <= n){
area = area + f(x)*pow(2,i%2 + 1)*h/3;
x+=h;
i++;
}
area -= (f(a) * h/3);
area -= (f(b) * h/3);
return area;
}
What I do is multiply each value of the function by either 2 or 4 (and h/3) with pow(2,i%2 + 1) and subtract off the edges as these should only have a weight of 1.
At first, I thought it worked just fine, however, when I compared it to my Trapezoidal Method function it was way more inaccurate which shouldn't be the case.
This is a simpler version of a code I previously wrote which had the same problem, I thought that if I cleaned it up a little the problem would go away, but alas. From another post, I get the idea that there's something going on with the types and the operations I'm doing on them which results in loss of precision, but I just don't see it.
Edit:
For completeness, I was running it for e^x from 1 to zero
\\function to be approximated
double f(double x){ double a = exp(x); return a; }
int main() {
int n = 11; //this method works best for odd values of n
double e = exp(1);
double exact = e-1; //value of integral of e^x from 0 to 1
cout << simp_rule(0,1,n,f) - exact;
The Simpson's Rule uses this approximation to estimate a definite integral:
Where
and
So that there are n + 1 equally spaced sample points xi.
In the posted code, the parameter n passed to the function appears to be the number of points where the function is sampled (while in the previous formula n is the number of intervals, that's not a problem).
The (constant) distance between the points is calculated correctly
double h = (b - a) / (n - 1);
The while loop used to sum the weighted contributes of all the points iterates from x = a up to a point with an ascissa close to b, but probably not exactly b, due to rounding errors. This implies that the last calculated value of f, f(x_n), may be slightly different from the expected f(b).
This is nothing, though, compared to the error caused by the fact that those end points are summed inside the loop with the starting weight of 4 and then subtracted after the loop with weight 1, while all the inner points have their weight switched. As a matter of fact, this is what the code calculates:
Also, using
pow(2, i%2 + 1)
To generate the sequence 4, 2, 4, 2, ..., 4 is a waste, in terms of efficency, and may add (depending on the implementation) other unnecessary rounding errors.
The following algorithm shows how to obtain the same (fixed) result, without a call to that library function.
template <typename func_type>
double simpson_rule(double a, double b,
int n, // Number of intervals
func_type f)
{
double h = (b - a) / n;
// Internal sample points, there should be n - 1 of them
double sum_odds = 0.0;
for (int i = 1; i < n; i += 2)
{
sum_odds += f(a + i * h);
}
double sum_evens = 0.0;
for (int i = 2; i < n; i += 2)
{
sum_evens += f(a + i * h);
}
return (f(a) + f(b) + 2 * sum_evens + 4 * sum_odds) * h / 3;
}
Note that this function requires the number of intervals (e.g. use 10 instead of 11 to obtain the same results of OP's function) to be passed, not the number of points.
Testable here.
The above excellent and accepted solution could benefit from liberal use of std::fma() and templatize on the floating point type.
https://en.cppreference.com/w/cpp/numeric/math/fma
#include <cmath>
template <typename fptype, typename func_type>
double simpson_rule(fptype a, fptype b,
int n, // Number of intervals
func_type f)
{
fptype h = (b - a) / n;
// Internal sample points, there should be n - 1 of them
fptype sum_odds = 0.0;
for (int i = 1; i < n; i += 2)
{
sum_odds += f(std::fma(i,h,a));
}
fptype sum_evens = 0.0;
for (int i = 2; i < n; i += 2)
{
sum_evens += f(std::fma(i,h,a);
}
return (std::fma(2,sum_evens,f(a)) +
std::fma(4,sum_odds,f(b))) * h / 3;
}
When I declare an array to store the Y values of each coordinate, define its values then use each of the element values to send into a rounding function, i obtain the error 'Run-Time Check Failure #2 - Stack around the variable 'Yarray; was corrupted. The output is mostly what is expected although i'm wondering why this is happening and if i can mitigate it, cheers.
void EquationElement::getPolynomial(int * values)
{
//Takes in coefficients to calculate Y values for a polynomial//
double size = 40;
double step = 1;
int Yarray[40];
int third = *values;
int second = *(values + 1);
int first = *(values + 2);
int constant = *(values + 3);
double x, Yvalue;
for (int i = 0; i < size + size + 1; ++i) {
x = (i - (size));
x = x * step;
double Y = (third *(x*x*x)) + (second *(x*x)) + (first * (x))
Yvalue = Y / step;
Yarray[i] = int(round(Yvalue)); //<-MAIN ISSUE HERE?//
cout << Yarray[i] << endl;
}
}
double EquationElement::round(double number)
{
return number < 0.0 ? ceil(number - 0.5) : floor(number + 0.5);
// if n<0 then ceil(n-0.5) else if >0 floor(n+0.5) ceil to round up floor to round down
}
// values could be null, you should check that
// if instead of int* values, you took std::vector<int>& values
// You know besides the values, the quantity of them
void EquationElement::getPolynomial(const int* values)
{
//Takes in coefficients to calculate Y values for a polynomial//
static const int size = 40; // No reason for size to be double
static const int step = 1; // No reason for step to be double
int Yarray[2*size+1]{}; // 40 will not do {} makes them initialized to zero with C++11 onwards
int third = values[0];
int second = values[1]; // avoid pointer arithmetic
int first = values[2]; // [] will work with std::vector and is clearer
int constant = values[3]; // Values should point at least to 4 numbers; responsability goes to caller
for (int i = 0; i < 2*size + 1; ++i) {
double x = (i - (size)) * step; // x goes from -40 to 40
double Y = (third *(x*x*x)) + (second *(x*x)) + (first * (x)) + constant;
// Seems unnatural that x^1 is values and x^3 is values+2, being constant at values+3
double Yvalue= Y / step; // as x and Yvalue will not be used outside the loop, no need to declare them there
Yarray[i] = int(round(Yvalue)); //<-MAIN ISSUE HERE?//
// Yep, big issue, i goes from 0 to size*2; you need size+size+1 elements
cout << Yarray[i] << endl;
}
}
Instead of
void EquationElement::getPolynomial(const int* values)
You could also declare
void EquationElement::getPolynomial(const int (&values)[4])
Which means that now you need to call it with a pointer to 4 elements; no more and no less.
Also, with std::vector:
void EquationElement::getPolynomial(const std::vector<int>& values)
{
//Takes in coefficients to calculate Y values for a polynomial//
static const int size = 40; // No reason for size to be double
static const int step = 1; // No reason for step to be double
std::vector<int> Yarray;
Yarray.reserve(2*size+1); // This is just optimization. Yarran *Can* grow above this limit.
int third = values[0];
int second = values[1]; // avoid pointer arithmetic
int first = values[2]; // [] will work with std::vector and is clearer
int constant = values[3]; // Values should point at least to 4 numbers; responsability goes to caller
for (int i = 0; i < 2*size + 1; ++i) {
double x = (i - (size)) * step; // x goes from -40 to 40
double Y = (third *(x*x*x)) + (second *(x*x)) + (first * (x)) + constant;
// Seems unnatural that x^1 is values and x^3 is values+2, being constant at values+3
double Yvalue= Y / step; // as x and Yvalue will not be used outside the loop, no need to declare them there
Yarray.push_back(int(round(Yvalue)));
cout << Yarray.back() << endl;
}
}
I was given a task to write a program that displays:
I coded this:
#include<iostream.h>
#include<conio.h>
void main()
{
clrscr();
int a, n = 1, f = 1;
float s = 0;
cin >> a;
while(n <= a)
{
f = f * n;
s += 1 / (float)f;
n = n + 1;
}
cout << s;
getch();
}
So this displays -
s = 1 + 1/2! + 1/3! + 1/4! .... + 1/a!, including odd and even factorials.
For the past two hours I am trying to figure out how can I modify this code so that it displays the desired result. But I couldn't figure it out yet.
Question:
What changes should I make to my code?
You need to accumulate the sum while checking the counter n and only calculate the even factorials:
int n;
double sum = 1;
cin >> n;
for(int i = 2; i < n; ++i{
if(i % 2 == 0) sum += 1 / factorial(i);
}
In your code:
while(n <= a)
{
f = f * n;
// checks if n is even;
// n even if the remainder of the division by 2 is zero
if(n % 2 == 0){
s += 1 / (float)f;
}
n = n + 1;
}
12! is the largest value that fits in an 32 bit integer. You should use double for all the numbers. For even factorials, starting with f = 1 (0!), f = f * (n-1) * n, where n = 2, 4, 6, 8, ... .
You have almost everything you need in place (assuming you don't want to make design changes based on the issues brought up in the comments).
All you need to change is what you multiply f by in each step. To build up n! you are multiplying by n in each step. To build up (2n)! you would multiply by 2*n*(2*n-1)
Edit: Your second theory about what the instructor wants would need only slightly more of a change. Your inner loop could be replaced by
while(n < a)
{
f = f * n * (n+1);
s += 1 / f;
n = n + 2;
}
Edit2: To run your program I made several changes for I/O things you did that don't work in my copy of GCC. Hopefully those won't distract from the main point of the following code. I also added a second, more complicated and more accurate method of computing the answer to see how much was lost in floating point rounding.
So this code computes the answer twice, once by the method I suggested you change your code to and once by a more accurate method (using double instead of float and adding the numbers in the more accurate sequence via a recursive function). Then it display your answer and the difference between the two answers.
Running that shows the version I suggested gets all the displayed digits correct and is only wrong for the values of a I tried by tiny amounts that would need more display precision to notice:
#include<iostream>
using namespace std;
double fac_sum(int n, int a, double f)
{
if ( n > a )
return 0;
f *= n * (n-1);
return fac_sum(n+2, a, f) + 1 / f;
}
int main()
{
int a, n = 1;
float f = 1;
float s = 0;
cin >> a;
while(n < a)
{
f = f * n * (n+1);
s += 1 / f;
n = n + 2;
}
cout << s;
cout << " approx error was " << fac_sum( 2, a, 1.0)-s;
return 0;
}
For 8 that displays 0.54308 approx error was -3.23568e-08
I hope you understand the e-08 notation meaning the error is in the 8'th digit to the right of the .
Edit3: I changed f to float in this post because I had copied/tested thinking f was float, so parts of my answer didn't make sense when f was int
The input should be n - the number of triangles (1 <= n <= 20) and afterwards n rows of three doubles each (corresponding to each of the triangles' sides). The output should be the "n" which has the maximum triangle area.
#include <iostream>
#include <math.h>
using namespace std;
const int MAX_SIZE = 20;
int main()
{
int n, s, p;
double max = 0;
cin >> n;
int x[MAX_SIZE];
for (int i = 0; i < n; i++)
{
double y[2];
for (int j = 0; j < 3; j++)
cin >> y[j];
p = (y[0] + y[1] + y[2]) / 2;
s = sqrt(p * (p - y[0]) * (p - y[1]) * (p - y[3]));
if (s >= max) max = s;
}
cout << max;
return 0;
}
That's what I've done so far. "p" stands for semiparameter by the way.. - I'm using Heron's formula. I haven't even got it to "cout" the n in which the area is max but rather the maximum area itself, yet it doesn't work but gives me a massive error instead. Any ideas?
You've got a few problems:
You need to change s and p from ints to doubles (otherwise you'll get unwanted truncation of your results).
You need to change double y[2]; to double y[3]; (since you need three side lengths, not two).
Change s = sqrt(p * (p - y[0]) * (p - y[1]) * (p - y[3])); to s = sqrt(p * (p - y[0]) * (p - y[1]) * (p - y[2])); (since y[3] is out of bounds of your array).
Note also that you can get rid of your array x, since you don't seem to actually use it anywhere.
You are allocation only 2 doubles. You need 3, try double y[3].
I managed to get my sqrt function to run perfectly, but I'm second guessing if I wrote this code correctly based on the pseudo code I was given.
Here is the pseudo code:
x = 1
repeat 10 times: x = (x + n / x) / 2
return x.
The code I wrote,
#include <iostream>
#include <math.h>
using namespace std;
double my_sqrt_1(double n)
{
double x= 1; x<10; ++x;
return (x+n/x)/2;
}
No, your code is not following your pseudo-code. For example, you're not repeating anything in your code. You need to add a loop to do that:
#include <iostream>
#include <math.h>
using namespace std;
double my_sqrt_1(double n)
{
double x = 1;
for(int i = 0; i < 10; ++i) // repeat 10 times
x = (x+n/x)/2;
return x;
}
Let's analyze your code:
double x = 1;
// Ok, x set to 1
x < 10;
// This is true, as 1 is less than 10, but it is not used anywhere
++x;
// Increment x - now x == 2
return (x + n / x) / 2
// return value is always (2 + n / 2) / 2
As you don't have any loop, function will always exit in the first "iteration" with the return value (2 + n / 2) / 2.
Just as another approach that you can use binary search or the another pretty elegant solution is to use the Newton's method.
Newton's method is a method for finding roots of a function, making use of a function's derivative. At each step, a value is calculated as: x(step) = x(step-1) - f(x(step-1))/f'(x(step-1)) Newton's_method
This might be faster than binary search.My implementation in C++:
double NewtonMethod(double x) {
double eps = 0.0001; //the precision
double x0 = 10;
while( fabs(x-x0) > eps) {
double a = x0*x0-n;
double r = a/(2*x0);
x = x0 - r;
x0 = x;
}
return x;
}
Since people are showing different approaches to calculating the square root, I couldn't resist ;)...
Below is the exact copy (with the original comments, but without preprocessor directives) of the inverse square root implementation from Quake III Arena:
float Q_rsqrt( float number )
{
long i;
float x2, y;
const float threehalfs = 1.5F;
x2 = number * 0.5F;
y = number;
i = * ( long * ) &y; // evil floating point bit level hacking
i = 0x5f3759df - ( i >> 1 ); // what the...?
y = * ( float * ) &i;
y = y * ( threehalfs - ( x2 * y * y ) ); // 1st iteration
// y = y * ( threehalfs - ( x2 * y * y ) ); // 2nd iteration, this can be removed
return y;
}