#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
setlocale(LC_ALL, "RU");
float P_a2, P_b2,result2,x,y,z;
cout << "P_a(x)= 9,09*x^9– 9,09*x^3+ 9,09*x\n";
cout << "P_b(x)= – 8980,032*x^6– 186,34*x^4– 649,23*x^2\n\n";
x = 1.2;
cout << "\n";
y = x * x * x * x * x * x;
P_a2 = ((9.09 * y - 9.09) * x * x + 9.09) * x;
cout << setprecision(9) << P_a2 << "\n\n";
z = x * x;
P_b2 = ((-8980.032 * z - 186.34) * z - 649.23) * z;
cout << setprecision(9) << P_b2 << "\n\n";
result2 = P_a2 * P_b2;
cout <<fixed<< setprecision(15) << result2 << "\n\n"; //prints -1184587.00000000
//right answer is -1 184 586,9806370984
}
Is this problem related with type of the value?
I really cant understand why it happens and what should i do...
Can somebody please explain why does it happens with result2 and can i avoid it without changing the type?
P.S my bad, i've forgot to add the minus, right answer ofc is
-1 184 586,9806370984
P.P.S yes, i know that this code can be optimized, but our teacher said us to do so.
And yes parentheses are correct.
I know i can fix it by using double, i'm just asking if i can solve this problem without using it
There are two issues (not c++ issues, more of general floating point numerical calculation issues):
float type is usually 6-7 decimal digits precision, using double would give you 15-16 decimal digits, more helpful for the problem. Seems like you need more digits than float to at least hold the result.
There is a subtraction in P_a, so should watch for catastrophic cancellation when grouping the terms.
Related
I have to take the coordinates of the vertices of a triangle from the user and tell if it is a right-angled triangle or not. I'm using Pythagoras Theorem to Find out i.e. h * h = b * b + p * p
But surprisingly this doesn't work for some specific right-angled triangles.
Here is one such Triangle:
Vertex A: (x, y) = (1, 3)
Vertex B: (x, y) = (1, 1)
Vertex C: (x, y) = (5, 1)
It calculates perfectly, which I figured out by printing the calculation, but still doesn't work.
Then I tried by using sqrt() function from the cmath library this way:
h = sqrt(b * b + p * p)
Logically it is the same, but it worked.
I want to understand, why the earlier method is not working?
Here is a simplified version of My Code:
#include <iostream>
#include <cmath>
using namespace std;
class Vertex {
double x, y;
public:
void take_input(char obj) {
cout << endl << " Taking Coordinates of Vertex " << obj << ": " << endl;
cout << " Enter the x component: ";
cin >> x;
cout << " Enter the y component: ";
cin >> y;
}
double distance(Vertex p) {
double dist = sqrt((x-p.x)*(x-p.x) + (y-p.y)*(y-p.y));
return dist;
}
};
class Triangle {
Vertex a, b, c;
public:
void take_inp(string obj) {
cout << endl << "Taking Vertices of the Triangle " << obj << ": " << endl;
cout << " Verteces should be in a counter clockwise order (as per convention)." << endl;
a.take_input('A');
b.take_input('B');
c.take_input('C');
}
void is_rt_ang() {
double h = a.distance(c)*a.distance(c);
double bp = a.distance(b)*a.distance(b) + b.distance(c)*b.distance(c);
/*
// Strangely this attempt works which is logically the same:
double h = a.distance(c);
double bp = sqrt(a.distance(b)*a.distance(b) + b.distance(c)*b.distance(c));
*/
if (h == bp) {
cout << "Angle is 90" << endl;
cout << h << " = " << bp << endl;
cout << "It is Right-Angled" << endl;
}
else {
cout << "Angle is not 90!" << endl;
cout << h << " != " << bp << endl;
cout << "It is Not a Right-Angled" << endl;
}
}
};
int main()
{
Triangle tri1, tri2;
tri1.take_inp("tri1");
tri1.is_rt_ang();
return 0;
}
The line
double dist = sqrt((x-p.x)*(x-p.x) + (y-p.y)*(y-p.y));
in the Vertex::distance method gives you an approximation of a square root which is rarely going to coincide with an exact answer. This is because most real numbers can't be represented in floating point arithmetic.
But in given code sample you can make do without sqrt. Replace Vertex::distance method with a method
double distance_square(Vertex p) {
double dist_square = (x-p.x)*(x-p.x) + (y-p.y)*(y-p.y);
return dist_square;
}
and call it like this in Triangle::is_rt_ang:
double h = a.distance_square(c);
double bp = a.distance_square(b) + b.distance_square(c);
This solution is still flawed because floating-point multiplication is also a subject to rounding errors. But if it is guaranteed that you are going to work only with integer coordinates, you can replace all doubles in your code with ints and for them there is no problem with multiplication (besides possibly going out of bounds for large numbers).
EDIT: Also a comment on printing
It calculates perfectly, which I figured out by printing the
calculation, but still doesn't work.
When you print doubles you need to set precision manually in order to avoid rounding. If in your code I replace a line
cout << h << " != " << bp << endl;
with
cout << std::setprecision(std::numeric_limits<double>::digits10) << std::fixed << h << " != " << bp << endl;
then for example triangle from the question I get the output
Angle is not 90!
20.000000000000004 != 20.000000000000000
It is Not a Right-Angled
For this to compile you will need to add #include <limits> and #include <iomanip>.
In your is_rt_ang function you're assuming that your hypotenuse is always going to be the edge AC, but it doesn't seem like you're doing anything to verify this.
double h = a.distance(c)*a.distance(c);
double bp = a.distance(b)*a.distance(b) + b.distance(c)*b.distance(c);
You could try getting the squares of all your distances first, (AC)^2, (AB)^2, and (BC)^2, then finding the candidate for hypotenuse by taking the max value out of the three, then do something like:
bool isRightTriangle = max == (min1 + min2)
You may also be running into some kind of round-off error with floating point numbers. It is common to use a an epsilon value when comparing floating point numbers because of the inherent round-off errors with them. If you don't need floating point values maybe use an integer, or if you do need floating point values try using an epsilon value in your equalities like:
abs(h - bp) <= epsilon
You should be able to find more information about floating point values, round-off errors, and machine epsilons on the web.
Here is a link to a SO Q/A that talks about floating point math that may be a good resource for you: Is floating point math broken?
I need to find function (1-exp(-x))/x values from 10^-30 to 10^9. But for very small numbers the output is 0 but it should be 1. X is correct but there're some issues with fx, and i've not idea how to solve it.
#include <math.h>
#include <iomanip>
int main()
{
double fx ,x;
x=pow(10.0L,-30);
std::cout<<"fx\t\t\t\t"<<"x\t\t"<<std::endl;
for(double i=0;x<pow(10,9);i+=0.01)
{
std::setprecision(20);
x=pow(10.0L,-30+i);
fx =(double)((1-exp(-pow(10,-30+i)))/pow(10,-30+i));
std::cout<<x<<"\t\t\t\t\t"<<fx<<std::endl;
}
}
My expected Output is:
for x ==10^-30 fx==1
But realoutput is:
for x ==10^-30 fx==0
You are right that fx should be equal to about 1 for small x.
The issue is that double has a finite precision. Its relative error is much higher than 10^{-30}.
A mantissa of at leat 100 bits would be needed.
This is illustrated by the following relation:
(1 - (1-x)) = 0
for very small x. See the code hereafter.
In other words, because of rounding errors, the addition is no longer associative.
A workaround is to use a different formula for very small x, for example less than 10^{10} in absolute value.
#include <iostream>
#include <cmath>
#include <iomanip>
int main()
{
double fx ,x;
x = pow(10.0L,-30);
std::setprecision(20);
fx = (1.0 - exp(-x)) / x;
std::cout << x << "\t" << fx << std::endl;
fx = (1.0 - (1.0 - x))/x;
std::cout << x << "\t" << fx << std::endl;
// for very small x:
fx = 1 - x/2 + (x*x)/6;
std::cout << x << "\t" << fx << std::endl;
}
Output:
1e-30 0
1e-30 0
1e-30 1
This question already has answers here:
Why does dividing two int not yield the right value when assigned to double?
(10 answers)
Closed 4 years ago.
double calculatePercentage(int unmatched, int charLen){
double percentageReturn = (((charLen - unmatched)/charLen) * 100);
cout << "percenpercentageReturntage " << percentageReturn << endl;
return percentageReturn;
}
I tried to calculate percentage of these values, but it returns 0. I tried with int, float and double but all returns 0.
Can anyone help me with this ?
You may typecast double while doing division and multiplication operation so that as a whole result will be in double. You may do something like this:
double percentageReturn = ( ( (double)(charLen - unmatched) / (double)charLen ) * 100.0 );
In the below statement, the right hand side of the assignment is evaluated first and then assigned to percentageReturn at which point the implicit conversion (if required) takes place.
double percentageReturn = (((charLen - unmatched)/charLen) * 100);
In the right hand side, all parameters are integers, so it will be integer division followed by the truncation of the result.
Since (charLen - unmatched) will be less than charLen, the truncated result will be 0.
To fix this, you can either cast the numerator or the denominator of the division to double and this will give you division without truncation.
(double)(charLen - unmatched) or (double)charLen.
The division operator / in C++, performs an integer division when its both sides are of integral type. To overcome this, you need to cast arguments to a floating-point type first, as follows:
double cl = static_cast<double>(charLen);
double um = static_cast<double>(unmatched);
Note that if you're using Modern C++, it's a good practice to do cast the implicitly convertible types with static_cast, instead of old C-style casts.
To solve your issue please try one of this two possible solution
#include <stdio.h>
#include <iostream>
#include <math.h>
using namespace std;
double calculatePercentage(int unmatched, int charLen) {
double percentageReturn = (((double)(charLen - unmatched) / (double)charLen) *
100);
cout << "percenpercentageReturntage_int " << percentageReturn << endl;
return percentageReturn;
}
double calculatePercentage(double unmatched, double charLen) {
double percentageReturn = (((charLen - unmatched) / charLen) * 100);
cout << "percenpercentageReturntage_double " << percentageReturn << endl;
return percentageReturn;
}
int main()
{
cout << "the integer function value is :" << calculatePercentage(4, 50) << endl;
cout << "the double function value is :" << calculatePercentage((double)4,
(double)50) << endl;
return 0;
}
Please have a look at the following code
#include <iostream>
#include <iomanip>
#include <cmath>
using namespace std;
int main()
{
//int side1 = 0;
//int side2 = 0;
//int rightSide = 0;
cout << "Right Side" << setw(10) << "Side1" << setw(10) << "Side2" << endl;
for(int i=1;i<=500;i++)
{
//side1++;
//cout << side1 << endl;
for(int a=1;a<=500;a++)
{
//side2++;
//cout << "side 2 " << side2 << endl;
for(int c=1;c<=500;c++)
{
//rightSide++;
int rightSideSqr = pow(c,c);
int side1Sqr = pow(i,i);
int side2Sqr = pow(a,a);
if(rightSideSqr == (side1Sqr+side2Sqr))
{
cout << rightSideSqr << setw(15) << i << setw(10) << a << endl;
}
}
}
}
}
This gives an error "PythagorialTriples.cpp:28: error: call of overloaded `pow(int&, int&)' is ambiguous". This doesn't happen if I simply used manual power like i*i, instead of the method. Can someone please explain me why this is happening? I am new to C++ anyway. Thanks
There are multiple overloads for pow defined in <cmath>. In your code, these 3 are all equally valid, therefore the compiler is having trouble choosing the right one:
pow(float, int);
pow(double, int);
pow(long double, int);
The simplest solution is to use static_cast on the first argument, to remove any ambiguity. e.g.
int side1Sqr = pow( static_cast<double>(i) ,i );
int side2Sqr = pow( static_cast<double>(a) ,a );
Whoa! Pow(x,y) is x raised to the yth power (in mathematical terms - xy)!! NOT x*y
So you're trying to take iith power in a 5003 nested loop. Probably not what you want. Replace with pow(i,2) for your desired behavior.
Note, #Mooing Duck raises an excellent point about x^y in c++ which is the XOR operator. But I think you sort of figured that out if you're already using pow anyway.
It cannot figure out which overloaded function to use.
Try
pow(double(i), i);
or
pow(double(i), 2);
Since that looks like what you want.
Are you sure that you can handle such a big pow?
Pow(x,y) is xy. Look at the
http://www.cplusplus.com/reference/clibrary/cmath/pow/
double pow ( double base, double exponent );
long double pow ( long double base, long double exponent );
float pow ( float base, float exponent );
double pow ( double base, int exponent );
long double pow ( long double base, int exponent );
There is no INT version. Your compiler didnt know which one is correct. You have to tell them by using static_cast like:
int side1Sqr = pow(static_cast<double>i,i);
for big precision calculate you can use:
http://gmplib.org/
There is also one solution from boost.
Im trying to convert radians to degrees, but im not getting the same results as google
calculator and the Pi i defined dosent output all number.
If you type in google search: (1 * 180) / 3.14159265 then you get 57.2957796, but my program is
outputting: 57.2958 and if you type in google search Pi you get: 3.14159265, but mine
dosent output the rest, it output: 3.14159
My code is:
#include <iostream>
#define SHOW(X) cout << # X " = " << (X) << endl
using namespace std;
double Pi_test = 3.14159265;
float radian_to_degree(double ENTER) {
double Pi = 3.14159265;
float degrees = (ENTER * 180) / Pi;
return degrees;
}
int main (int argc, char * const argv[]) {
SHOW( radian_to_degree(1) ); // 57.2958 not 57.2957795 like google, why?
SHOW( Pi_test ); // output 3.14159' not 3.14159265, why?
return 0;
}
Please help me fix this, what wrong? any example?
You need to change the default precision:
cout.precision(15);
cout << d << endl;
As stated here, it may be that cout in C++ is rounding your number before displaying it. Try this:
#define SHOW(X) cout << setprecision(some_number) << # X " = " << (X) << endl
Change radian_to_degree to operate on double not float, since double has more precision.
Output the result using std::setprecision
#include <iomanip>
std::cout << std::setprecision(9) << result << "\n";
Even after you change cout's precision, note that double only contains so much data; if you expect your program to spit out 1000 decimal places, a double is not going to give you that much. You'd have to create a data type of your own.
Also, don't define macro functions unless you have to.