c++ get negative numbers from complex - c++

If I create a complex number with amplitude negativ (-1) and no phase (0), thus corresponding to a double of -1, and convert it back to amplitude and phase, the amplitude is not negative
complex<double> c;
c = polar(-1.0, 0.0);
cout << c << ", " << abs(c) << ", " << arg(c) << endl;
the output is
(-1, 0), 1, -3.14159
it should have been
(-1, 0), -1, 0
How can I get back the correct amplitude value?

From a mathematical point of view, the magnitude (or modulus or absolute value) of a complex number should be a positive number (or 0).
Looking at the reference page for std::polar it's specified that:
Returns a complex number with magnitude r and phase angle theta. The
behavior is undefined if r is negative or NaN, or if theta is infinite
(since C++17)
You don't specify what compiler you are using, but it is kind enough to give you the "correct" result, a complex number with magnitude 1 and phase angle -π.
Testing the same snippet with g++ 6.1 (-std=c++14) gave me:
(-1,-0), 1, -3.14159
The only difference is the negative zero, which is consistent with the negative angle.
Also note that a function like std::abs could return a negative number only if some error occured.

You're confusing real and imaginary part with absolute and phase.
Try:
cout << c << ", " << real(c) << ", " << imag(c) << endl;
Also, absolute values can NEVER be negative by definition of polar coordinates. You could try with that:
complex<double> c;
c = polar(1.0, M_PI); //don't forget to include <cmath>
cout << c << ", " << abs(c) << ", " << arg(c) << endl;
And that will flip the phase and make the radius on the other direction of the polar coordinates.

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?

Returning incorrect values of floor function in C++ [duplicate]

This question already has answers here:
Is floating point math broken?
(31 answers)
Closed 2 years ago.
The code:
cout << log(25.0/9.0)/log(5.0/3.0) << endl << floor(log(25.0/9.0)/log(5.0/3.0));
results:
2
1
Why does C++ considers floor(2) = 1?
What I tried:
When saving the fraction in a float it returns the correct value:
float a = log(25.0/9.0)/log(5.0/3.0);
cout << a << endl << floor(a);
results:
2
2
Set your precision. floor is correct;
std::cout << std::fixed << std::setprecision(20) << std::endl << log(25.0 / 9.0) / log(5.0 / 3.0) << std::endl << floor(log(25.0 / 9.0) / log(5.0 / 3.0)) << std::endl;
float a = log(25.0 / 9.0) / log(5.0 / 3.0);
std::cout << std::fixed << std::setprecision(20) << std::endl<< a << std::endl << floor(a) << std::endl;
double b = log(25.0 / 9.0) / log(5.0 / 3.0);
std::cout << std::fixed << std::setprecision(20) << std::endl << b << std::endl << floor(b) << std::endl;
this produces
1.99999999999999955591
1.00000000000000000000
2.00000000000000000000
2.00000000000000000000
1.99999999999999955591
1.00000000000000000000
I complied and checked the whole code and let me share my analysis with you.
If you do log(25.0/9.0)/log(5.0/3.0) division directly the compiler treats it as double and the double division result is equal to 1.9999999999999996. If it is rounded it will become 2 and if floor operation is done on this it will become 1 as floor() function in C++ returns the largest possible integer value which is less than or equal to the given argument. In this example it will always return 1.
If the division log(25.0/9.0)/log(5.0/3.0) is treated as float it will result in 2.0000000039152304 (treating each operand as float and storing result in double for understanding) hence in this case round and floor operation will have same result that is 2.
Good Luck
I had same problem two days ago when I was solving a problem on Codeforces. I was using floor function and its returning its different value. I went to google and found some answers here on stackoverflow telling me to use cout << std::fixed, but this function will return float values with decimal point which is not accepted on Codeforces. After a little bit of google search I found this following formula to calculate floor value of a/b.
floor = (a/b) + ((a%b)!=0)
Hope this helps :)

C++ if-statement for maximum value in array not pointing to correct element

I've an array of 2500 steps taken by a robot, each step taken in a random direction (up, down, right, or left). I'm supposed to store the Euclidian distance (a right triangle's hypotenuse) of each step from the robot's origin. No problem there.
I'm also supposed to keep tabs on the max. Euclidian distance the robot reaches, so if the current distance is greater than one of the previous ones, the current one becomes the new greatest distance. Here's my code:
int main(){
int steps[2500];
int randDir[2500];
int coords[2] = {0,0};
int path[2500][2];
double eucliDist[2500];
eucliDist[0] = 1;
double maxEucliDist;
double taxiDist;
for (int i = 0; i < 2500; i++){
randDir[i] = rand() % 4;
steps[i] = i + 1;
switch(randDir[i]){
case 0:
coords[0] = coords[0] + 1;
break;
case 1:
coords[1] = coords[1] + 1;
break;
case 2:
coords[0] = coords[0] - 1;
break;
case 3:
coords[1] = coords[1] - 1;
break;
}
eucliDist[i] = sqrt((pow(coords[0],2)) + (pow(coords[1],2)));
if (eucliDist[i] > eucliDist[i-1]){
maxEucliDist = eucliDist[i]; //need to fix this. Not showing true max Euclid. Dist.
taxiDist = abs(coords[0]) + abs(coords[1]);
}
//cout << "Step " << steps[i] << " Euclidian distance from origin is: " << eucliDist[i] <<endl; //check euclidian dist each step
//cout << steps[i] << "\t Coords (" << coords[0] << ", " << coords[1] << ")" << "\n"; //check coords with each step
}
cout << "Final Coordinates: (" << coords[0] << ", " << coords[1] << ")" << endl;
cout << "Maximum Euclidian distance was: " << maxEucliDist << endl;
cout << "'Taxicab' distance is: " << taxiDist << endl;
cin.get();}
Problem is that my output shows the wrong max, as shown in the snippet of my output below:
Program output showing incorrect maximum Euclidian distance
FYI, "taxicab" distance is the distance a 2nd robot would have to take to get to the 1st robot's position at max distance if it needed to (it's a right triangle's base + height since traveling on a grid).
Not sure what I'm doing wrong. Might have something to do with my if-statement in the bottom half of the code.
Any thoughts?
Your problem is indeed your if-statement:
if (eucliDist[i] > eucliDist[i-1]){ // THIS IS WRONG
maxEucliDist = eucliDist[i]; // THIS IS ACTUALLY OK
taxiDist = abs(coords[0]) + abs(coords[1]);
}
You're comparing your current distance to the distance in the PREVIOUS frame, not your maximum. You also need to initialize your maximum to zero, since it needs something to start with too, or else your comparison will be "current" versus "garbage". C++ does not initialize local variables to zero.
Your new if-statement should be this:
if (eucliDist[i] > maxEucliDist){
maxEucliDist = eucliDist[i];
taxiDist = abs(coords[0]) + abs(coords[1]);
}
Your first job is to recognise that the square of a positive number is a monotonic function of the number. So stop taking those square roots all over the place (which are difficult for a computer to evaluate), and work in distance squared, until you come to display the final result.
Then you can replace the nasty pow(x, 2) functions with x * x and work in integer arithmetic. (Take steps to avoid overflowing an int though.). This will be at least an order of magnitude faster.
Your specific issue is a logic error in that you are only comparing your new distance with the previous one, not the minimum found thus far.

two equal calculations not returning the same result

I got two different .cpp files with two equal calculations.. But they don't return the same results?
A code
double theta = (double)maxLoc.y/angleBins*CV_PI;
std::cout << theta << " " << abs(sin(theta)) << std::endl;
A result
1.53589 0.999391
B code
double theta = (double)maxLoc.y / angleBins * CV_PI;
std::cout << theta << " " << abs(sin(theta)) << std::endl;
B result
1.53589 0
You're probably calling the abs function from C in the second code snippet which takes an int as parameter. Using std::abs in both code snippets (and the correct header #include<cmath>) will fix the problem.

Should C++ std::uniform_real_distribution<double> only generate positive numbers?

I was trying to generate some random doubles in C++ (MSVC, though that isn't too important to me—I just didn't have another compiler to test) and I noticed that my quick program never generated negative numbers:
#include <iostream>
#include <random>
#include <ctime>
int main() {
std::mt19937 generator(clock());
std::uniform_real_distribution<double>
rand_dbl(std::numeric_limits<double>::min(),
std::numeric_limits<double>::max());
std::cout << "Double Limits: (" << std::numeric_limits<double>::min()
<< "," << std::numeric_limits<double>::max() << ")"
<< std::endl << std::endl;
int total_neg = 0;
for (int i=0; i<100; i++) {
double d = rand_dbl(generator);
if (d<0) total_neg++;
std::cout << d << " ";
}
std::cout << std::endl << std::endl
<< "Total negative random double is: " << total_neg << std::endl;
return 0;
}
No matter how many numbers I have it generate, it never generates a negative one. I understand why most of the numbers generated are in the 10307 - 10308 range (which isn't exactly what I wanted), but not why the numbers are always positive. I tried a few different generators (default, mt19937, minstd_rand0) without any difference in this aspect.
Can anyone describe why this is the case?
You set it up that way with the limits that you provided. std::numeric_limits<double>::min() gives the smallest positive double, and you used that as the lower bound on the distribution.
std::numeric_limits<double>::min()
Will return DBL_MIN which is the smalles value closest to 0 a double can hold. If you want the largest negative value then you need to use
std::numeric_limits<double>::lowest()
Which will return -DBL_MAX which is the largest negative value a double can hold.
From cppreference:
For floating-point types with denormalization, min returns the minimum positive normalized value.
(emphasis mine)
So it's pretty normal you only get positive values.
Could you tell what is displayed by those lines?
std::cout << "Double Limits: (" << std::numeric_limits<double>::min()
<< "," << std::numeric_limits<double>::max() << ")"
<< std::endl << std::endl;