Printf'ing floating point numbers in C++ gives zeroes - c++

I am doing some c++ right now and stumbled on a problem I can't get to wrap my head around.
I am doing a floating point comparison like this:
if(dists.at<float>(i,0) <= 0.80 * dists.at<float>(i,1)) {
matched = true;
matches++;
} else {
printf((dists.at<float>(i,0) <= 0.80 * dists.at<float>(i,1)) ? "true\n" : "false");
printf("threw one away because of dist: %f/%f\n", dists.at<float>(i,0),dists.at<float>(i,1));
}
at the first line, the comparison threw a false what means: dists[0] > dists[1]
When we print the values, the results are this:
falsethrew one away because of dist: 0.000000/0.000000
falsethrew one away because of dist: 0.000000/0.000000
I think it has something to do with the results not being a float or something, but I'm no pro at C++ so I could use some help to find out what these values are.

Looks like it was due to the number being too small.
In response to #NirMH, I am posting my comment as an answer.
%g instead of %f can print very small floating point numbers.
There are other options such as %e, as #ilent2 mentioned in the comment.
For example:
double num = 1.0e-23;
printf("%e, %f, %g", num, num, num);
prints out the following result:
1.000000e-023, 0.000000, 1e-023

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.

Arduino double subtraction returning 0 erronously

I have a function that takes as parameter some double and does a subtraction operation on it. However I'm getting a result of 0 when one of the parameter is 0 for some reason.
int calcPID(double current, double desired, double k){
double diff;
diff = desired - current;
Serial.print("desired = ");
Serial.print(desired);
Serial.print(" ,current = ");
Serial.print(current);
Serial.print(",diff = ");
Serial.println(diff);
int r = (int)diff;
return r;
}
output
desired = 250.00 ,current = 1.69,diff = 248.31
desired = 250.00 ,current = 0.00,diff = 0.00
When the current is 0.00 the result(diff) is also 0.00 when it should be 250. Can someone tell me what's going on?
edit:
found out that I was getting a garbage value for current somehow that's not a double (I wrote 2 if conditions if current > 1 and if current <= 1 and neither of them were true).
This is very strange indeed.
I would suggest to create a second, minimal function like this:
int calcPID2(double current, double desired){
Serial.println(desired - current);
return(1);
}
and then gradually changing it to your original version, and see where it goes wrong (if it goes wrong..).
I have had some strange things with the Arduino software too in the past. Maybe you should check if you have the latest version.
You might also want to check if there is no memory or stack problem (i.e. if you have enough free memory left).
I think it's something with the floating point calculation. Have a look at this: https://www.arduino.cc/en/Reference/Float or google it and you will find pretty good answers :)

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
}