C++ basics - If statement testing - c++

it's my first day messing around with C++. I'm trying to do just a really basic code looking for the roots in a quadratic equation. Here is my code so far:
#include <iostream>
#include <cmath>
int main () {
int a, b, c;
double root1, root2;
std::cout << "Enter the integers a, b, and c to fit in the quadratic equation: ax^2 + bx + c >> " << std::endl;
std::cout << "a = ";
std::cin >> a;
std::cout << "b = ";
std::cin >> b;
std::cout << "c = ";
std::cin >> c;
std::cout <<"\n";
std::cout << "Quadratic equation to solve is : " << a << "x^2 + " << b << "x + " << c <<std::endl;
root1 = (-b + sqrt(b*b - 4*a*c))/(2*a);
root2 = (-b - sqrt(b*b - 4*a*c))/(2*a);
if (root1 && root2 != nan) {
std::cout << "root 1 = " << root1 << std::endl;
std::cout << "root 2 = " << root2 << std::endl;
}
else
std::cout << "no root exists" << std::endl;
return 0;
}
I'm getting this error:
invalid operands to binary expression ('double' and 'double (*)(const char *)')
in the line:
if (root1 && root2 != nan)
I'm looking for a simple test to see if the roots exist and this obviously doesn't work. Thanks in advance for your help!

To check if something is a real number, use isnan:
if(!isnan(root1) && !isnan(root2))
Explanation:
isnan determines if the given floating point number arg is not-a-number (NaN). It returns true if arg is NaN, false otherwise.
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. In C++, it is implemented with function overloads for each floating-point type, each returning a bool value.

double (*)(const char *) is a type which represents a pointer to a function that returns a double and takes a const char * argument. You'll find if you look at a reference for cmath that nan is the function in question.
Looks like you should be able to call it with an empty string to get a suitable value:
nan("")
However, you can't provide a double on one side of && and a bool on the other, so you'll need to have a suitable test for root1 as well.
And yes, that type syntax for nan is a bit crazy, that's how C does function pointer syntax, and the name of a function by itself represents a pointer to it, so that's what you get out of the compiler because C++ inherited C-style function pointers.

Use (C++11):
#include <cmath>
...
if (!isnan(root1) && !isnan(root2))

Use if (root1 != nan("") && root2 != nan(""))
The problem is in two places:
root1 is always true except when it is 0
nan is not declared, it should be nan("")
But I think it is better to use !isnan(root1) instead of just nan

Related

Specific right-angled Triangles are not being recognized as right-angled in Cpp

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?

Why in C++ do static_cast<unsigned> of negative numbers differ if the number is constant or not

What's the C++ rules that means equal is false?. Given:
float f {-1.0};
bool equal = (static_cast<unsigned>(f) == static_cast<unsigned>(-1.0));
E.g. https://godbolt.org/z/fcmx2P
#include <iostream>
int main()
{
float f {-1.0};
const float cf {-1.0};
std::cout << std::hex;
std::cout << " f" << "=" << static_cast<unsigned>(f) << '\n';
std::cout << "cf" << "=" << static_cast<unsigned>(cf) << '\n';
return 0;
}
Produces the following output:
f=ffffffff
cf=0
The behaviour of your program is undefined: the C++ standard does not define the conversion of a negative floating point type to an unsigned type.
(Note the familiar wrap-around behaviour only applies to negative integral types.)
So therefore there's little point in attempting to explain your program output.

separating decimal points into two integers

I have been given double x = 23.456; and two integer d and c.
I have to break it so that d gets the value 23 and c gets the value 456.
I thought of the following:-
int d;
d=(int)x;
but I cannot think of what to do with c as it is an integer and if i write
c=(x-d)*1000;
then it might be applicable for this case only and not for any other case.
Is there any way to get the number of digits after the decimal and then multiply it with equal number of zeros.
Please help!!!
You could repeatedly multiply it by 10, until there is nothing after decimal point.
double c = x - d;
while(c - floor(c) > 0.0)
{c *= 10;}
you may also need to #include <math.h> for floor function, which rounds down a number. e.g. floor(4.9) returns 4.0
Floating point calculations are little bit tricky in C++ (same is true for Java and other languages). You should avoid their direct comparison and do some other stuff to get predictable result when using them, consider:
double d1=1.1;
double d2= d1 / 10.0;
if(d2==0.11)cout << "equals" << endl;
else cout << "not equals" << endl; //result is "not equals"
d1=1.99;
float f1=0.01f;
double d3=d1+f1;
if(d3==2.0)cout << "equals" << endl;
else cout << "not equals" << endl; //result is "not equals"
d1=1.99;
d2=0.01;
d3=d1+d2-2.0;
if(d3==0.0)cout << "equals" << endl;
else cout << "not equals" << endl; //result is "not equals"
As for practical solution of the problem I can suggest 2 variants:
Var 1 is to use a function that allows to specify number of digits:
#include <iostream>
#include <cmath>
using namespace std;
void split_double(const double value, int& i_part, int& r_part,
const int max_digits_after_dp, int min_digits_after_dp){
auto powerOfTenL = [](int power){ int result = 1;
for(int i=0;i<power;++i)result *= 10;
return result;
};
//Get integral part
i_part = (int)value;
double temp = (value-i_part);
double pOfTen = powerOfTenL(max_digits_after_dp);
temp *= pOfTen;
//Get real part
r_part = round(temp);
//Remove zeroes at the right in real part
int num_of_d = max_digits_after_dp;
if(min_digits_after_dp>max_digits_after_dp)
min_digits_after_dp=max_digits_after_dp;
while (num_of_d>min_digits_after_dp) {
//If the number is divisible by 10, divide it by 10
if(0==(r_part%10)) { r_part /=10; num_of_d--;
}
else break; //Last digit is not 0
}
}
int main(int argc, char *argv[])
{
double value = 10.120019;
int ipart,rpart;
const int digitsMax = 6;
const int digitsMin = 3;
split_double(value,ipart,rpart,digitsMax,digitsMin);
cout<<"Double " <<value << " has integral part " <<ipart
<<" and real part "<<rpart<<endl;
return 0;
}
Second variant to solve the problem is to use C/C++ formatting functions like vsprintf and then split the resulting string.

error: called object type 'double' is not a function or function pointer

I am relatively new to c++ programming, I have an assignment to code the Newton Raphson method however I have the error error:
called object type 'double' is not a function or function pointer
This error appears when I am trying to compile my code. I tried some basic changes to assign pointer but I probably did it in the wrong way, my code is printed below, can anybody explain how can I overcome this?
#include <iostream>
#include <math.h>
using namespace std;
double f(double x); //this is f(x)
double f(double x) {
double eq1 = exp(x) + pow(x,3) + 5;
return eq1;
}
double f1(double x); //this is the first derivative f'(x)
double f1(double x) {
double eq2 = exp(x) + 3*pow(x,2);
return eq2;
}
int main() {
double x, xn, f, f1, eps;
cout << "Select first root :" << '\n'; //Here we select our first guess
cin >> xn;
cout << "Select Epsilon accuracy :" << '\n';
cin >> epsi;
f = f(x);
f1 = f1(x);
cout << "x_n" << " " << "x_(n+1)" << " " << "|x_(n+1) - x_1|" << '\n';
do {
x = xn; //This is the first iteneration step where x takes the value of the last itenarated (known) root xn
f = f(x);
f1 = f1(x);
xn = x - (f/f1); //this the formula that sets the itenaration going
cout << x << " " << xn << " " << fabs(xn - x) << '\n';
}
while( fabs(xn - x) < epsi ); //If |x_(n+1) - x_n| is smaller than the desired accurcay than the itenaration continues
cout << "The root of the equation is " << xn << '\n';
return 0;
}
Thank you
You have local variables with the same name as the functions, thus
f = f(x);
f1 = f1(x);
cannot work.
Rename either the functions or the variables. Anyhow single letter variable/function names are not nice. Use descriptive names. You (or anybody else) taking a look at the code after some weeks will be thankful for that.
PS: you also dont need the forward declarations. And the functions can be written a bit shorter:
//double f(double x); // this you dont need
double f(double x) {
return exp(x) + pow(x,3) + 5;
}
Also using namespace std; is considered bad practice. In this case it does little to no harm, but you better get rid of this bad habit before it does matter.
Last but not least you should format your code properly. This
while( fabs(xn - x) < epsi );
looks very nasty, because it seems to be an infinite loop. I almost never use the do-while loop, however, I suggest you to write it like this:
do {
// ...
} while ();
because usually whenever you see a while with a ; in the same line you should start to panic ;) (while loops are much more common than do-while and errors caused by a ; after the condition in a while loop can be a pain in the a** to debug)
You are attempting to use functions called f and f1 and doubles called f and f1. If you call the variables or the function something else, then you can resolve the error. It would be good coding practice to give these variables better names that tell the reader what they do and avoid mistakes like this one.
There were several errors in your code. I made it compilable:
#include <iostream>
#include <math.h>
using namespace std;
double func(double x); //this is f(x)
double func(double x) {
double eq1 = exp(x) + pow(x,3) + 5;
return eq1;
}
double func1(double x); //this is the first derivative f'(x)
double func1(double x) {
double eq2 = exp(x) + 3*pow(x,2);
return eq2;
}
int main() {
double x, xn, f, f1, eps;
cout << "Select first root :" << '\n'; //Here we select our first guess
cin >> xn;
cout << "Select Epsilon accuracy :" << '\n';
cin >> eps;
f = func(x);
f1 = func1(x);
cout << "x_n" << " " << "x_(n+1)" << " " << "|x_(n+1) - x_1|" << '\n';
do {
x = xn; //This is the first iteneration step where x takes the value of the last itenarated (known) root xn
f = func(x);
f1 = func1(x);
xn = x - (f/f1); //this the formula that sets the itenaration going
cout << x << " " << xn << " " << fabs(xn - x) << '\n';
}
while( fabs(xn - x) < eps ); //If |x_(n+1) - x_n| is smaller than the desired accurcay than the itenaration continues
cout << "The root of the equation is " << xn << '\n';
return 0;
}
The main problems were:
you defined the variable f with the same name of the f(x) function (the same error was repeated for the f'(x) function) and
you declared the eps variable to represent epsilon in your program but you tried to access to it several times by calling it epsi.

Check double variable if it contains an integer, and not floating point

What I mean is the following:
double d1 =555;
double d2=55.343
I want to be able to tell that d1 is an integer while d2 is not. Is there an easy way to do it in c/c++?
Use std::modf:
double intpart;
modf(value, &intpart) == 0.0
Don't convert to int! The number 1.0e+300 is an integer too you know.
Edit: As Pete Kirkham points out, passing 0 as the second argument is not guaranteed by the standard to work, requiring the use of a dummy variable and, unfortunately, making the code a lot less elegant.
Assuming a c99 and IEEE-754 compliant environment,
(trunc(x) == x)
is another solution, and will (on most platforms) have slightly better performance than modf because it needs only to produce the integer part. Both are completely acceptable.
Note that trunc produces a double-precision result, so you don't need to worry about out of range type conversions as you would with (int)x.
Edit: as #pavon points out in a comment, you may need to add another check, depending on whether or not you care about infinity, and what result you want to get if x is infinite.
Assuming you have the cmath <math.h> library, you can check the number against it's floor. If the number might be negative, make sure you get the absolute first.
bool double_is_int(double trouble) {
double absolute = abs( trouble );
return absolute == floor(absolute);
}
avakar was almost right - use modf, but the detail was off.
modf returns the fractional part, so the test should be that the result of modf is 0.0.
modf takes two arguments, the second of which should be a pointer of the same type as the first argument. Passing NULL or 0 causes a segmentation fault in the g++ runtime. The standard does not specify that passing 0 is safe; it might be that it happens to work on avakar's machine but don't do it.
You could also use fmod(a,b) which calculates the a modulo b passing 1.0. This also should give the fractional part.
#include<cmath>
#include<iostream>
int main ()
{
double d1 = 555;
double d2 = 55.343;
double int_part1;
double int_part2;
using namespace std;
cout << boolalpha;
cout << d1 << " " << modf ( d1, &int_part1 ) << endl;
cout << d1 << " " << ( modf ( d1, &int_part1 ) == 0.0 ) << endl;
cout << d2 << " " << modf ( d2, &int_part2 ) << endl;
cout << d1 << " " << ( modf ( d2, &int_part2 ) == 0.0 ) << endl;
cout << d2 << " " << modf ( d2, &int_part2 ) << endl;
cout << d1 << " " << ( modf ( d2, &int_part2 ) == 0.0 ) << endl;
cout << d1 << " " << fmod ( d1, 1.0 ) << endl;
cout << d1 << " " << ( fmod ( d1, 1.0 ) == 0 ) << endl;
cout << d2 << " " << fmod ( d2, 1.0 ) << endl;
cout << d2 << " " << ( fmod ( d2, 1.0 ) == 0 ) << endl;
cout.flush();
modf ( d1, 0 ); // segfault
}
int iHaveNoFraction(double d){
return d == trunc(d);
}
Now, it wouldn't be C if it didn't have about 40 years of language revisions...
In C, == returns int but in C++ it returns bool. At least on my Linux distro (Ubuntu) you need to either declare double trunc(double); or you could compile with -std=c99, or declare the level macro, all in order to get <math.h> to declare it.
How about
if (abs(d1 - (round(d1))) < 0.000000001) {
printf "Integer\n"; /* Can not use "==" since we are concerned about precision */
}
Fixed up to work using rounding to reflect bug Anna found
Alternate solutions:
if ((d1 - floor(d1) < 0.000000001) || (d1 - floor(d1) > 0.9999999999)) {
/* Better store floor value in a temp variable to speed up */
printf "Integer\n"; /* Can not use "==" since we are concerned about precision */
}
Theres also another one with taking floor, subtracting 0.5 and taking abs() of that and comparing to 0.499999999 but I figure it won't be a major performance improvement.
Just compare ceil and floor value of d
return floor(d)==ceil(d);
So, for d1=555, the above statement will return 555==555, i.e, true, so it's an integer.
And for d2=555.6, the above statement will return 555==556, i.e, false, so it's a double.
How about this?
if ((d1 - (int)d1) == 0)
// integer
#define _EPSILON_ 0.000001
bool close_to_int(double &d)
{
double integer,
fraction = modf(d, &integer);
if(fraction < _EPSILON_)
{
d = integer;
return true;
}
if((1.0 - fraction) < _EPSILON_)
{
d = integer + 1;
return true;
}
return false;
}
This looks at both side of the integer value and sets the value of d if it is within the limits of an integer value.
try:
bool isInteger(double d, double delta)
{
double absd = abs(d);
if( absd - floor(absd) > 0.5 )
return (ceil(absd) - absd) < delta;
return (d - floor(absd)) < delta;
}
#include <math.h>
#include <limits>
int main()
{
double x, y, n;
x = SOME_VAL;
y = modf( x, &n ); // splits a floating-point value into fractional and integer parts
if ( abs(y) < std::numeric_limits<double>::epsilon() )
{
// no floating part
}
}
In many calculations you know that your floating point results will have a small numerical error that can result from a number of multiplications.
So what you may really want to find is the question is this number within say 1e-5 of an integer value. In that case I think this works better:
bool isInteger( double value )
{
double flr = floor( value + 1e-5 );
double diff = value - flr;
return diff < 1e-5;
}
I faced a similar questions.
As I needed to round the double anyway, that's what I find working:
double d = 2.000000001;
int i = std::round(d);
std::fabs(d-i) < 10 * std::numeric_limits<double>::epsilon()
modf uses std::nearbyint(num) that why you should use nearbyint which return a double without decimal and may be faster.
#include <iostream>
#include <cmath>
int main() {
double number = 55.12;
if (!(number - std::nearbyint(number))) {
std::cout << "Is integer!";
} else {
std::cout << "Has decimal!";
}
return 0;
}
A sample code snipped that does it:
if ( ABS( ((int) d1) - (d1)) )< 0.000000001)
cout <<"Integer" << endl;
else
cout <<"Flaot" << endl;
EDIT: Changed it to reflect correct code.
Below you have the code for testing d1 and d2 keeping it very simple. The only thing you have to test is whether the variable value is equal to the same value converted to an int type. If this is not the case then it is not an integer.
#include<iostream>
using namespace std;
int main()
{
void checkType(double x);
double d1 = 555;
double d2 = 55.343;
checkType(d1);
checkType(d2);
system("Pause");
return 0;
}
void checkType(double x)
{
if(x != (int)x)
{
cout<< x << " is not an integer "<< endl;
}
else
{
cout << x << " is an integer " << endl;
}
};