Why this program is giving nan is the distance between the points? - c++

Why this program is giving nan is the distance between the points?
I have made it to use friend function and oop concept but whenever i try to find the distance between coords it shows either zero of nan
#include<iostream>
#include<cmath>
using namespace std;
class point{
int x,y;
friend void disCoord(point,point);
public:
point(int a,int b){
x=a;
y=b;
}
void displaypoint(){
cout<<"the point is("<<x<<","<<y<<")"<<endl;
}
};//END OF CLASS
void disCoord(point o1,point o2){
double dis=sqrt(pow(o2.x-o1.x,2)-pow(o2.y-o1.y,2));
cout<<"The distance between point"<<"("<<o1.x<<","<<o1.y<<") and point"<<"("<<o2.x<<","
<<o2.y<<") is "<<dis<<endl;
}
int main(){
point A=point(1,2);
point B=point(1,3);
A.displaypoint();
B.displaypoint();
disCoord(A,B);
return 0;
}

The problem is that you are using incorrect formula which result in taking square root of negative number. In particular, in your case
dis = sqrt((1-1)2 - (3-2)2)
= sqrt(0 - 1) = sqrt(-1)
And i quote from nan documentation
The NaN values are used to identify undefined or non-representable values for floating-point elements, such as the square root of negative numbers or the result of 0/0.
To solve this, replace double dis=sqrt(pow(o2.x-o1.x,2)-pow(o2.y-o1.y,2)); with:
double dis=sqrt(pow(o2.x-o1.x,2) + pow(o2.y-o1.y,2));
Note there is a + in between while you were using - for some reason.
This is because the actual(correct) formula for calculating distance is:
d(P,Q) = sqrt((x2-x1)2 + (y2-y1)2)

As others said, the formula you're using is incorrect. BUT, the reason you're getting a NaN or 0 as a result is slightly more complicated.
Your test points (1,2) and (1,3) share the same X component. So, your formula:
double dis=sqrt(pow(o2.x-o1.x,2)-pow(o2.y-o1.y,2));
Resolves to:
dis = sqrt(pow(1-1,2) - pow(3-2,2))
or
dis = sqrt(0 - 1)
Which we all affectionately know as i, the square root of -1. That's one of the few cases that will (correctly) yield a result of NaN. (NAN means "Not A Number," in case that wasn't clear.)
The correct distance formula:
sqrt(pow(o2.x-o1.x,2) + pow(o2.y-o1.y,2))
Doesn't allow for a negative argument to sqrt, so this never happens.
It's tough to find these issues if you're not sure what you're looking for. It'd be easier to debug if you didn't do everything on one line:
double a2 = pow(o2.x-o1.x,2);
double b2 = pow(o2.y-o1.y,2);
double c2 = a2 + b2;
double c = sqrt(c2);
That's overly verbose, but the general idea is to split complex statements up into components. It's easier to read, easier to debug, and, if you'd done this, you'd have seen that c2 was negative.
White space is cheap, carriage returns cost nothing. Don't scrimp on keystrokes in order to save time.

Related

Recursion for evaluating log(1+x) using taylor series of the same

#include<iostream>
using namespace std;
double log(double x,int n)
{
static double p = x ;
double s;
if(n==1)
return x;
else
{
s=log(x,n-1);
p*=x;
if(n%2==0)
return s - (p/n);
else
return s + (p/n);
}
}
int main()
{
double r = log(1,15);
cout << r;
return 0;
}
I tried writing the above function for evaluating the log(1+x) function using its taylor series with recursion. But it didn't gave the result as I expected.
Eg :
ln(2) = 0.693 whereas my code gave 0.725. In the above code, n represents the number of terms.
Also I am new to this platform, so can I say that the above question is complete or does it need some additional information for further explanation?
There is nothing wrong with that piece of code: this has obviously got to do with the rate of convergence of the Taylor series.
If you take n = 200 instead of n = 15 in your code, the approximation error will be low enough that the first two decimals of the exact solution ln(2) = 0.693147... will be the correct ones.
The more you increase the n parameter, the better approximation you will get of ln(2).
Your program does converge to the right number, just very slowly...
log(1,15) returns 0.725, as you noticed, log(1,50) is 0.683, log(1,100) is 0.688, and log(1,200) is 0.691. That's getting close to the number you expected, but still a long way to go...
So there is no C++ or recursion bug in your code - you just need to find a better Taylor series to calculate log(X). Don't look for a Taylor series for log(1+x) - these will typically assume x is small, and converge quickly for small x, not for x=1.

Is there a way we can use comparison operator with complex and real numbers?

I want to compare determinant, but i write it like this it gets error and is not executing. How can I compare complex no with real no for using if else condition.
I am using that if condition because I want that if roots are real then answer will not be in imaginary form like x+0i or (x,0). I simply want answer to be x.
#include <iostream>
#include <complex>
#include <cmath>
#include <iomanip>
using namespace std;
int main()
{
complex <double> a,b,c;
complex <double> x1,x2;
cout<<setprecision(3);
cout<<"Coefficient of square term: "; cin>>a;
cout<<"Coefficient of linear term: "; cin>>b;
cout<<"Coefficient of constant term: "; cin>>c;
complex <double> det=(b*b)-(4.0*a*c);
if (det>=0.0)
{
x1=(-b+sqrt(det))/(2.0*a);
x2=(-b-sqrt(det))/(2.0*a);
cout<<x1<<" "<<x2;
}
else
{
x1=(-b+sqrt(det))/(2.0*a);
x2=(-b-sqrt(det))/(2.0*a);
cout<<showpos;
cout<<x1.real()<<x1.imag()<<"i \n"<<x2.real()<<x2.imag()<<"i";
}
}
As discussed, it's questionable whether you really want to have an operator to do this. The operator compares modulae, and it will probably be clearer in the code to do that explicitly.
However, operators can be overridden as top level functions, do if you really want to, here' the code:
template<typename T>
bool operator >= (const complex<T>& l, const T& r)
{
return (l.imag() * l.imag() + l.real() * l.real()) >= r * r;
}
Though of course here you're doing a comparison with zero, and the modulus can never be negative, so I think your logic may be at fault somewhere.
It's more of a math misunderstanding, I guess.
The standard quadratic equation would have real coefficients a, b, c. Then det is also real and it can easily be checked for det >= 0. Which you have to do if you want to restrict to real solutions. But you don't have to check if you use complex x1, x2, because the complex numbers will handle sqrt(-1) automatically.
If you really want to have complex a, b, c, the formulae are also fine. There is no mathematical meaning in det >= 0 for complex det. The only interesting case you might want to check is det == 0 resulting in x1 and x2 being equal.
Aha, now I finally get what you want to check. Case one is for real solutions! To get that right, you have to check that det is real and not negative. I would write this as
if ( ( det - conj(det) == 0.0 ) && ( real(det) >= 0.0 ) ) { ... }
Note that you have to write 0.0 to clarify that it is a double. Also note that the simpler imag(det) == 0.0 for checking if it is real might run into 'the usual' problems with comparing floating point numbers directly.
// Read about the complex number comparison
// how on earth you can compare imaginary number with a real number
if (det.real() >= 0)
{
x1 = (-b+sqrt(det))/(2.0*a);
x2 = (-b-sqrt(det))/(2.0*a);
cout<<x1<<" "<<x2;
}
A complex number is a combination of both real and imaginary numbers, how can you compare a complex number with an imaginary number?
If you want to compare, then you need to compare the real part with real part and complex with complex.

Calculating the value of arctan(x) in C++

I have to calculate the value of arctan(x) . I have calculated the value of this by evaluating the following series :
Arctan (x) = x – x^3/3 + x^5/5 – x^7/7 + x^9/9 - …
But the following code can not calculate the actual value. For example, calculate_angle(1) returns 38.34 . Why?
const double DEGREES_PER_RADIAN = 57.296;
double calculate_angle(double x)
{
int power=5,count=3;
double term,result,prev_res;
prev_res = x;
result= x-pow(x,3)/3;
while(abs(result-prev_res)<1e-10)
{
term = pow(x,power)/power;
if(count%2==0)
term = term*(-1);
prev_res=result;
result=result+term;
++count;
power+=2;
// if(count=99)
// break;
}
return result*DEGREES_PER_RADIAN;
}
EDIT: I found the culprit. You forgot to include stdlib.h, where the function abs resides. You must have ignored the warning about abs being implicitly declared. I checked that removing the include yields the result 38.19 and including it yields the result ~45.
The compiler is not required to stop compilation when an undeclared function is being used (in this case abs). Instead, it is allowed to make assumptions on how the function is declared (in this case, wrong one.)
Besides, like other posters already stated, your use of abs is inappropriate as it returns an int, not a double or float. The condition in the while should be >1e-100 not <1e-100. The 1e-100 is also too small.
--
You forgot to increase count and power after calculating the first two summands:
prev_res = x;
result= x-pow(x,3)/3;
count = 4; <<<<<<
power = 5; <<<<<<
while(abs(result-prev_res)<1e-100)
{
term = pow(x,power)/power;
if(count%2==1)
term = term*(-1);
Also I consider your use of the count variable counterintuitive: it is intialized with 3 like if it denotes the last used power; but then, loop iterations increase it by 1 instead of 2 and you decide the sign by count%2 == 1 as opposed to power%4 == 3
The series converges to tan^{-1} x, but not very fast. Consider the series when x=1:
1 - 1/3 + 1/5 - 1/7 + 1/9 - ...
What is the error when truncating at the 1/9 term? It's around 1/9. To get 10^{-100} accuracy, you would need to have 10^{100} terms. The universe would end before you'd get that. And, catastrophic round-off error and truncation error would make the answer utterly unreliable. You only have 14 digits to play with for doubles.
Look at reference works like Abramowitz and Stegun [AMS 55] or the new NIST Digital Library of Mathematical Functions at http://dlmf.nist.gov to see how these are done in practice. Often, one uses Padé approximants instead of Taylor series. Even when you stick with Taylor series, you often use Chebyshev approximation to cut down on the total error.
I also recommend Numerical Methods that [Usually] Work, by Forman Acton. Or the Numerical Recipes in ... series.
Your sign is the wrong way around after the first two terms. It should be:
if(count%2==0)
term = term*(-1);
Your comparison is the wrong way around in the while condition. Also, you're expecting an unrealistically high level of precision. I would suggest something more like this:
while(fabs(result-prev_res)>1e-8)
Finally, you'll get a more accurate result with a better value for DEGREES_PER_RADIAN. Why not something like this:
const double DEGREES_PER_RADIAN = 180/M_PI;

Condition operators (< , >) do not work in gsl interpolation function

I have a question that seems very unusual to me. I have a condition statement that doesn't work as it should. Particularly, I have
double maxx = *max_element(v1.begin(), v1.end());
if(x > maxx){
cout << x << "\t" << maxx << endl;
}
where v1 is a vector. The weird thing is the output: it gives me equal numbers, i.g.
168.68 168.68
This statement is related to gsl interpolation function. In fact, it duplicates a statement in interp.c:150 that causes an error of gsl: interp.c:150: ERROR: interpolation error. So when a number that should be executed normally comes to the function it actually gives true instead of false and I have no idea why, as the number (x) is actually equal to the maximal value allowed.
P.S.: I have checked the if statement on its own (with elementary entries) and it seems to work fine.
P.P.S.: A piece of code from interp.c:
double gsl_interp_eval (const gsl_interp * interp,
const double xa[], const double ya[], double x,
gsl_interp_accel * a){
double y;
int status;
if (x < interp->xmin || x > interp->xmax)
{
GSL_ERROR_VAL("interpolation error", GSL_EDOM, GSL_NAN);
}
status = interp->type->eval (interp->state, xa, ya, interp->size, x, a, &y);
DISCARD_STATUS(status);
return y;}
So it returns an error even for x = interp->xmax, although it definitely should not.
UPDATE: I changed double to long double in declaration. This fixed some places (I use this function more than once), but not all of them.
Looks like floating point inaccuracy. Try printing the values without limiting the number decimal places or printing (x-maxx) as suggested by Oli Charlesworth.
The usual solution to this kind of problem is to apply a small 'epsilon' on comparisons.
Floating point is a tricky business, especially when comparing values. If the values are very close, they may well print the same, but still be different.
Have a look at:
http://floating-point-gui.de/

Is this the correct way to test to see if two lines are colinear?

My code in the colinear does not seem to work and its frustrating the hell out of me. Am i going the best way to use my line class by using two points in my point class? My test for colinearlirty is crashing so I am stuck in a rut for the past few days.
bool line::isColinear(line)
{
bool line2=false;
line l1,l2;
if (l1.slope()==l2.slope())
{
if (l1.y_int()==l2.y_int())
{
line2 =true;
return line2;
}
}
else
{
line2 =false;
}
}
//Heres a copy of my line class
class line
{
private:
point p1,p2;
public:
bool isColinear(line);
bool isParallel(line);
point solve(line);
double slope();
double y_int();
void Display(ostream&);
};
You are storing line as between two points. Slope of a line is usually defined as
slope = (y2 - y1) / ( x2 - x1 )
if x1 is equal to x2, you can have a division by zero error/exception.
Other things to be careful about
If you are storing point coordinates as integers, you could be doing just a integer division and not get what you expect
If you are using doubles throughout, please use a tolerance when comparing them
There's not nearly enough here to really judge what's going wrong, so a few generalities:
Never compare floating-point values directly for equality. It won't work a surprising amount of the time. Instead, compare their difference with an amount so small that you're content to call it "zero" (normally we call it "epsilon"):
if (abs((num1 - num2)) < 0.001) {
/* pretend they're equal */
} else {
/* not equal */
}
line2 is unnecessary in this example. You might as well return true or false directly from the conclusions. Often even the return true or return false is needlessly confusing. Lets assume you re-write this method a little to three methods. (Which might or might not be an improvement. Just assume it for a bit.)
bool line::compare_slope(line l2) {
return fabs((l2.slope() - self.slope()) < 0.001; // don't hardcode this
}
bool line::compare_origin(line l2) {
return fabs((l2.y_int() - self.y_int()) < 0.001; // nor this
}
bool line::is_colinear(line l2) {
return compare_slope(l2) && compare_origin(l2);
}
No true or false hard coded anywhere -- instead, you rely on the value of the conditionals to compute true or false. (And incidentally, the repetition in those functions goes to show that a function floating_comparison(double f1, double f2, double epsilon), could make it far easier to modify epsilon either project-wide or compute an epsilon based on the absolute values of the floating point numbers in question.)
My guess is that since l1 and l2 are uninitialized, their slope methods are doing a divide by zero. Initialize those properly or switch to the proper variables and you'll fix your crash.
Even once you get that working, the test is likely to fail. You can't compare floating point numbers and expect them to be equal, even if it seems they ought to be equal. You should read What Every Computer Scientist Should Know About Floating-Point Arithmetic.
A simple formula for a line (in 2D) (derived from here) is:
P1(x1,y1) and P2(x2,y2) are the points determining the line.
(y-y1) (x2-x1) + (y1-y2) (x-x1) = 0 ( let's use f(x,y) = 0 )
To test if two lines match imagine that a second line is defined by points P3(x3,y3), P4(x4,y4).
To make sure that those lines are 'quite' the same you should test if the two points (P3, P4) determining the second line are close 'enough' to the previous line.
This is easily done by computing f(x3,y3) and f(x4,y4). If those values are close to 0 then the lines are the same.
Pseudocode:
// I would chose tolerance around 1
if ( f(x3,y3) < tolerance && f(x4,y4) < tolerance )
{
// line P1,P2 is the same as P3,P4
}