How to check for undefined value of a double? - c++

I am trying to figure out a way to check for a undefined value of a slope in which case it would be vertical. I have tried using NULL but that doesn't seem to work.
double Point::Slope(Point &p2)
{
double slop = 0;
slop = (y - p2.y) / (x - p2.x);
if (slop == NULL)
{
slop = 10e100;
}
return slop;
}

If you mean nan ('not a number') with "undefined", you should avoid computing one in the first place, i.e. by checking that the denominator of a '/' operation is not zero. Second, you can always check for nan by
#include <cmath>
bool std::isnan(x); // since C++11
bool isnan(x); // pre C++11, from the C math library, defined as macro
see the man pages, or cppreference.

In C++, NULL == 0. This is not what you seek.
Maybe this may help you : http://www.gnu.org/s/hello/manual/libc/Infinity-and-NaN.html
Try the isnan(float) function.

I'd recommend avoiding the divide-by-zero all together (by the way... why don't you call it slope instead of slop?):
double Point::Slope(Point&p2)
{
double slope = 0;
double xDelta = x - p2.x;
double yDelta = y - p2.y;
if (xDelta != 0)
{
slope = yDelta / xDelta;
}
return slope;
}

Related

Doubles rounding again

In my program there are some precisions (some positive integer, in the most cases it supposed to be of the form ) for some doubles, so that double * precision should become an integer.
But as we all know floating point numbers are inaccurate, so, for example 1.3029515 could be saved as 1.3029514999999998..., and in my program I need to write such floating point number to a file, but I want this 1.3029515 to be written instead of something like 1.3029514999999998....
Previously only precision of form was used in my program, and I've reached the wanted result with a piece of code like below:
// I have a function for doubles equality check
inline bool sameDoubles(const double& lhs, const double& rhs, const double& epsilon) {
return fabs(lhs - rhs) < epsilon;
}
inline void roundDownDouble(double& value, const unsigned int& numberOfDigitsInFraction = 6) {
assert(numberOfDigitsInFraction <= 9);
double factor = pow(10.0, numberOfDigitsInFraction);
double oldValue = value;
value = (((int)(value * factor)) / factor);
// when, for example, 1.45 is stored as 1.4499999999..., we can get wrong value, so, need to do the check below
double diff = pow(10.0, 0.0 - numberOfDigitsInFraction);
if(sameDoubles(diff, fabs(oldValue - value), 1e-9)) {
value += diff;
}
};
But now, I can't reach wanted results with the same technique, I've tried with a function below, but have not succeeded:
// calculates logarithm of number with given base
double inline logNbase(double number, double base) {
return log(number)/log(base);
}
// sameDoubles function is the same as in above case
inline void roundDownDouble(double& value, unsigned int precision = 1e+6) {
if(sameDoubles(value, 0.0)) { value = 0; return; }
double oldValue = value;
value = ((long int)(value * precision) / (double)precision);
// when, for example, 1.45 is stored as 1.4499999999..., we can get wrong value, so, need to do the check below
int pwr = (int)(logNbase((double)precision, 10.0));
long int coeff = precision / pow(10, pwr);
double diff = coeff * pow(10, -pwr);
if(sameDoubles(diff, fabs(oldValue - value), diff / 10.0)) {
if(value > 0.0) {
value += diff;
} else {
value -= diff;
}
}
}
For 1.3029515 value and precision = 2000000 this function returns incorrect 1.302951 value (expression (long int)(value * precision) becomes equal to 2605902 instead of 2605903).
How can I fix this? Or maybe there is a some smart way to make this rounding happen correctly?
You're doing your rounding the hard way. Do it the easy way instead:
double rounding = 0.5;
if (value < 0.0) rounding = -0.5;
value = ((long int)(value * precision + rounding) / (double)precision);
Now there's no need for the rest of the code.

simulated annealing algorithm

I implemented simulated annealing in C++ to minimize (x-2)^2+(y-1)^2 in some range.
I'm getting varied output which is not acceptable for this type of heuristic method. It seems that the solution is converging but never quite closing in on the solution.
My code:
#include <bits/stdc++.h>
using namespace std;
double func(double x, double y)
{
return (pow(x-2, 2)+pow(y-1, 2));
}
double accept(double z, double minim, double T,double d)
{
double p = -(z - minim) / (d * T);
return pow(exp(1), p);
}
double fRand(double fMin, double fMax)
{
double f = (double)rand() / RAND_MAX;
return fMin + f * (fMax - fMin);
}
int main()
{
srand (time(NULL));
double x = fRand(-30,30);
double y = fRand(-30,30);
double xm = x, ym=y;
double tI = 100000;
double tF = 0.000001;
double a = 0.99;
double d=(1.6*(pow(10,-23)));
double T = tI;
double minim = func(x, y);
double z;
double counter=0;
while (T>tF) {
int i=1;
while(i<=30) {
x=x+fRand(-0.5,0.5);
y=y+fRand(-0.5,0.5);
z=func(x,y);
if (z<minim || (accept(z,minim,T,d)>(fRand(0,1)))) {
minim=z;
xm=x;
ym=y;
}
i=i+1;
}
counter=counter+1;
T=T*a;
}
cout<<"min: "<<minim<<" x: "<<xm<<" y: "<<ym<<endl;
return 0;
}
How can I get it to reach the solution?
There are a couple of things that I think are wrong in your implementation of the simulated annealing algorithm.
At every iteration you should look at some neighbours z of current minimum and update it if f(z) < minimum. If f(z) > minimum you can also accept the new point, but with an acceptance probability function.
The problem is that in your accept function, the parameter d is way too low - it will always return 0.0 and never trigger the condition of acceptance. Try something like 1e-5; it doesn't have to be physically correct, it only has to decrease while lowering the "temperature".
After updating the temperature in the outer loop, you should put x=xm and y=ym, before doing the inner loop or instead of searching the neigbours of the current solution you will basically randomly wander around (you aren't checking any boundaries too).
Doing so, I usually get some output like this:
min: 8.25518e-05 x: 2.0082 y: 0.996092
Hope it helped.

Algorithm for movement along linear line

Code:
I have a function as follows:
bool Action::approach (img_comp &mover, sf::Vector2f start, sf::Vector2f end, int speed)
{
//Get the change in x and y
float delta_x = (end.x - start.x) / speed;
float delta_y = (end.y - start.y) / speed;
//Move the sprite
mover.sprite.move(delta_x, delta_y);
//Check if the sprite has met the end
if (mover.sprite.getPosition() == end)
return true;
return false;
}
(Where sf::Vector2f is basically a struct with an x and y float parameter, e.g. a point on an x-y grid)
Question:
Unsurprisingly, this function has a possibility to never return true after passing the end point due to the rounding of float. What algorithm do I use in this scenario to have my sprite land exactly on the end point, regardless of rounding?
Note: Tolerance is not an answer to my question. It is merely a compromise. I want the algorithm that picks the points perfectly the first time, regardless of any rounding. If this is impossible, let me know.
i think you have the answer already, because of the rounding of float you should not do mover.sprite.getPosition() == end but to see if mover.sprite.getPosition() - end is smaller then some number, lets say
float diff = mover.sprite.getPosition() - end;
if (diff < 0)
diff *= -1;
//Check if the sprite has met the end
if (diff > 0.01)
return true;
that way you check not if you are on the spot but if you are close enough to the spot.
to improve that you can also do:
float diff = mover.sprite.getPosition() - end;
if (diff < 0)
diff *= -1;
//Check if the sprite has met the end
if (diff > 0.01){
mover.sprite.getPosition() = end; //this might not be the exact syntax but the idea is clear i hope
return true;
}
Your sprite can go to the left or to the right, so you should consider to use absolute difference between current position and end point.
Epsilon = 1e-9
deltaX = (end.x - start.x) / speed
deltaY = (end.y - start.y) / speed
dirX = Math.sgn(deltaX)
dirY = Math.sgn(deltaY)
mover.sprite.move(deltaX, deltaY);
crossedEndX = dirX * (mover.sprite.getPosition().x - end.x) > Epsilon
crossedEndY = dirY * (mover.sprite.getPosition().y - end.y) > Epsilon
if(crossedEndX && crossedEndY)
return true
Instead of a direct compare, you could do something like "if point is close to end then point = end"
/* Set TOLERANCE to whatever makes sense.
* Could have different X and Y values too...
*/
#define TOLERANCE 0.01
sf::Vector2f &newPos = mover.sprite.getPoition();
if (abs(newPos[0] - end[0]) < TOLERANCE &&
abs(newPos[1] - end[1]) < TOLERANCE) {
{
mover.sprite.setPosition(end);
result = true;
}

Sort points by angle from given axis?

How can I sort an array of points/vectors by counter-clockwise increasing angle from a given axis vector?
For example:
If 0 is the axis vector I would expect the sorted array to be in the order 2, 3, 1.
I'm reasonably sure it's possible to do this with cross products, a custom comparator, and std::sort().
Yes, you can do it with a custom comparator based on the cross-product. The only problem is that a naive comparator won't have the transitivity property. So an extra step is needed, to prevent angles either side of the reference from being considered close.
This will be MUCH faster than anything involving trig. There's not even any need to normalize first.
Here's the comparator:
class angle_sort
{
point m_origin;
point m_dreference;
// z-coordinate of cross-product, aka determinant
static double xp(point a, point b) { return a.x * b.y - a.y * b.x; }
public:
angle_sort(const point origin, const point reference) : m_origin(origin), m_dreference(reference - origin) {}
bool operator()(const point a, const point b) const
{
const point da = a - m_origin, db = b - m_origin;
const double detb = xp(m_dreference, db);
// nothing is less than zero degrees
if (detb == 0 && db.x * m_dreference.x + db.y * m_dreference.y >= 0) return false;
const double deta = xp(m_dreference, da);
// zero degrees is less than anything else
if (deta == 0 && da.x * m_dreference.x + da.y * m_dreference.y >= 0) return true;
if (deta * detb >= 0) {
// both on same side of reference, compare to each other
return xp(da, db) > 0;
}
// vectors "less than" zero degrees are actually large, near 2 pi
return deta > 0;
}
};
Demo: http://ideone.com/YjmaN
Most straightforward, but possibly not the optimal way is to shift the cartesian coordinates to be relative to center point and then convert them to polar coordinates. Then just subtract the angle of the "starting vector" modulo 360, and finally sort by angle.
Or, you could make a custom comparator for just handling all the possible slopes and configurations, but I think the polar coordinates are little more transparent.
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
struct Point {
static double base_angle;
static void set_base_angle(double angle){
base_angle = angle;
}
double x;
double y;
Point(double x, double y):x(x),y(y){}
double Angle(Point o = Point(0.0, 0.0)){
double dx = x - o.x;
double dy = y - o.y;
double r = sqrt(dx * dx + dy * dy);
double angle = atan2(dy , dx);
angle -= base_angle;
if(angle < 0) angle += M_PI * 2;
return angle;
}
};
double Point::base_angle = 0;
ostream& operator<<(ostream& os, Point& p){
return os << "Point(" << p.x << "," << p.y << ")";
}
bool comp(Point a, Point b){
return a.Angle() < b.Angle();
}
int main(){
Point p[] = { Point(-4., -4.), Point(-6., 3.), Point(2., -4.), Point(1., 5.) };
Point::set_base_angle(p[0].Angle());
sort(p, p + 4, comp);
Point::set_base_angle(0.0);
for(int i = 0;i< 4;++i){
cout << p[i] << " angle:" << p[i].Angle() << endl;
}
}
DEMO
Point(-4,-4) angle:3.92699
Point(2,-4) angle:5.17604
Point(1,5) angle:1.3734
Point(-6,3) angle:2.67795
Assuming they are all the same length and have the same origin, you can sort on
struct sorter {
operator()(point a, point b) const {
if (a.y > 0) { //a between 0 and 180
if (b.y < 0) //b between 180 and 360
return false;
return a.x < b.x;
} else { // a between 180 and 360
if (b.y > 0) //b between 0 and 180
return true;
return a.x > b.x;
}
}
//for comparison you don't need exact angles, simply relative.
}
This will quickly sort them from 0->360 degress. Then you find your vector 0 (at position N), and std::rotate the results left N elements. (Thanks TomSirgedas!)
This is an example of how I went about solving this. It converts to polar to get the angle and then is used to compare them. You should be able to use this in a sort function like so:
std::sort(vectors.begin(), vectors.end(), VectorComp(centerPoint));
Below is the code for comparing
struct VectorComp : std::binary_function<sf::Vector2f, sf::Vector2f, bool>
{
sf::Vector2f M;
IntersectComp(sf::Vector2f v) : M(v) {}
bool operator() ( sf::Vector2f o1, sf::Vector2f o2)
{
float ang1 = atan( ((o1.y - M.y)/(o1.x - M.x) ) * M_PI / 180);
float ang2 = atan( (o2.y - M.y)/(o2.x - M.x) * M_PI / 180);
if(ang1 < ang2) return true;
else if (ang1 > ang2) return false;
return true;
}
};
It uses sfml library but you can switch any vector/point class instead of sf::Vector2f. M would be the center point. It works great if your looking to draw a triangle fan of some sort.
You should first normalize each vector, so each point is in (cos(t_n), sin(t_n)) format.
Then calculating the cos and sin of the angles between each points and you reference point. Of course:
cos(t_n-t_0)=cos(t_n)cos(t_0)+sin(t_n)sin(t_0) (this is equivalent to dot product)
sin(t_n-t_0)=sin(t_n)cos(t_0)-cos(t_n)sin(t_0)
Only based on both values, you can determine the exact angles (-pi to pi) between points and reference point. If just using dot product, clockwise and counter-clockwise of same angle have same values. One you determine the angle, sort them.
I know this question is quite old, and the accepted answer helped me get to this, still I think I have a more elegant solution which also covers equality (so returns -1 for lowerThan, 0 for equals, and 1 for greaterThan).
It is based on the division of the plane to 2 halves, one from the positive ref axis (inclusive) to the negative ref axis (exclusive), and the other is its complement.
Inside each half, comparison can be done by right hand rule (cross product sign), or in other words - sign of sine of angle between the 2 vectors.
If the 2 points come from different halves, then the comparison is trivial and is done between the halves themselves.
For an adequately uniform distribution, this test should perform on average 4 comparisons, 1 subtraction, and 1 multiplication, besides the 4 subtractions done with ref, that in my opinion should be precalculated.
int compareAngles(Point const & A, Point const & B, Point const & ref = Point(0,0)) {
typedef decltype(Point::x) T; // for generality. this would not appear in real code.
const T sinA = A.y - ref.y; // |A-ref|.sin(angle between A and positive ref-axis)
const T sinB = B.y - ref.y; // |B-ref|.sin(angle between B and positive ref-axis)
const T cosA = A.x - ref.x; // |A-ref|.cos(angle between A and positive ref-axis)
const T cosB = B.x - ref.x; // |B-ref|.cos(angle between B and positive ref-axis)
bool hA = ( (sinA < 0) || ((sinA == 0) && (cosA < 0)) ); // 0 for [0,180). 1 for [180,360).
bool hB = ( (sinB < 0) || ((sinB == 0) && (cosB < 0)) ); // 0 for [0,180). 1 for [180,360).
if (hA == hB) {
// |A-ref|.|B-ref|.sin(angle going from (B-ref) to (A-ref))
T sinBA = sinA * cosB - sinB * cosA;
// if T is int, or return value is changed to T, it can be just "return sinBA;"
return ((sinBA > 0) ? 1 : ((sinBA < 0) ? (-1) : 0));
}
return (hA - hB);
}
If S is an array of PointF, and mid is the PointF in the centre:
S = S.OrderBy(s => -Math.Atan2((s.Y - mid.Y), (s.X - mid.X))).ToArray();
will sort the list in order of rotation around mid, starting at the point closest to (-inf,0) and go ccw (clockwise if you leave out the negative sign before Math).

Returning double with precision

Say I have a method returning a double, but I want to determine the precision after the dot of the value to be returned. I don't know the value of the double varaible.
Example:
double i = 3.365737;
return i;
I want the return value to be with precision of 3 number after the dot
Meaning: the return value is 3.365.
Another example:
double i = 4644.322345;
return i;
I want the return value to be: 4644.322
What you want is truncation of decimal digits after a certain digit. You can easily do that with the floor function from <math.h> (or std::floor from <cmath> if you're using C++):
double TruncateNumber(double In, unsigned int Digits)
{
double f=pow(10, Digits);
return ((int)(In*f))/f;
}
Still, I think that in some cases you may get some strange results (the last digit being one over/off) due to how floating point internally works.
On the other hand, most of time you just pass around the double as is and truncate it only when outputting it on a stream, which is done automatically with the right stream flags.
You are going to need to take care with the borderline cases. Any implementation based solely on pow and casting or fmod will occasionally give wrong results, particularly so an implementation based on pow(- PRECISION).
The safest bet is to implement something that neither C nor C++ provide: A fixed point arithmetic capability. Lacking that, you will need to find the representations of the pertinent borderline cases. This question is similar to the question on how Excel does rounding. Adapting my answer there, How does Excel successfully Rounds Floating numbers even though they are imprecise? , to this problem,
// Compute 10 to some positive integral power.
// Dealing with overflow (exponent > 308) is an exercise left to the reader.
double pow10 (unsigned int exponent) {
double result = 1.0;
double base = 10.0;
while (exponent > 0) {
if ((exponent & 1) != 0) result *= base;
exponent >>= 1;
base *= base;
}
return result;
}
// Truncate number to some precision.
// Dealing with nonsense such as nplaces=400 is an exercise left to the reader.
double truncate (double x, int nplaces) {
bool is_neg = false;
// Things will be easier if we only have to deal with positive numbers.
if (x < 0.0) {
is_neg = true;
x = -x;
}
// Construct the supposedly truncated value (round down) and the nearest
// truncated value above it.
double round_down, round_up;
if (nplaces < 0) {
double scale = pow10 (-nplaces);
round_down = std::floor (x / scale);
round_up = (round_down + 1.0) * scale;
round_down *= scale;
}
else {
double scale = pow10 (nplaces);
round_down = std::floor (x * scale);
round_up = (round_down + 1.0) / scale;
round_down /= scale;
}
// Usually the round_down value is the desired value.
// On rare occasions it is the rounded-up value that is.
// This is one of those cases where you do want to compare doubles by ==.
if (x != round_up) x = round_down;
// Correct the sign if needed.
if (is_neg) x = -x;
return x;
}
You cannot "remove" precision from a double. You could have: 4644.322000. It's a different number but the precision is the same.
As #David Heffernan said do it when you convert it to a string for display.
You want to truncate your double to n decimal places, then you can use this function:
#import <cmath>
double truncate_to_places(double d, int n) {
return d - fmod(d, pow(10.0, -n));
}
Instead of multiplying and dividing by powers of 10 like the other answers, you can use the fmod function to find the digits after the precision you want, and then subtract to remove them.
#include <math.h>
#define PRECISION 0.001
double truncate(double x) {
x -= fmod(x,PRECISION);
return x;
}
There is no good way to do this with plain doubles, but you can write a class or simply struct like
struct lim_prec_float {
float value;
int precision;
};
then have your function
lim_prec_float testfn() {
double i = 3.365737;
return lim_prec_float{i, 4};
}
(4 = 1 before point + 3 after. This uses a C++11 initialization list, it would be better if lim_prec_float was a class with proper constructors.)
When you now want to output the variable, do this with a custom
std::ostream &operator<<(std::ostream &tgt, const lim_prec_float &v) {
std::stringstream s;
s << std::setprecision(v.precision) << v.value;
return (tgt << s.str());
}
Now you can, for instance,
int main() {
std::cout << testfn() << std::endl
<< lim_prec_float{4644.322345, 7} << std::endl;
return 0;
}
which will output
3.366
4644.322
this is because std::setprecision means rounding to the desired number of places, which is likely what you really want. If you actually mean truncate, you can modify the operator<< with one of the truncation functions given by the other answers.
In the same way you format a date before displaying it, you should do the same with double.
However, here are two approaches I have used for rounding.
double roundTo3Places(double d) {
return round(d * 1000) / 1000.0;
}
double roundTo3Places(double d) {
return (long long) (d * 1000 + (d > 0 ? 0.5 : -0.5)) / 1000.0;
}
The later is faster, however numbers cannot be larger than 9e15