Right, I think I really am living a dream. I have the following piece of code which I compile and run on an AIX machine:
AIX 3 5
PowerPC_POWER5 processor type
IBM XL C/C++ for AIX, V10.1
Version: 10.01.0000.0003
#include <stdio.h>
#include <math.h>
#define RADIAN(x) ((x) * acos(0.0) / 90.0)
double nearest_distance(double radius,double lon1, double lat1, double lon2, double lat2){
double rlat1=RADIAN(lat1);
double rlat2=RADIAN(lat2);
double rlon1=lon1;
double rlon2=lon2;
double a=0,b=0,c=0;
a = sin(rlat1)*sin(rlat2)+ cos(rlat1)*cos(rlat2)*cos(rlon2-rlon1);
printf("%lf\n",a);
if (a > 1) {
printf("aaaaaaaaaaaaaaaa\n");
}
b = acos(a);
c = radius * b;
return radius*(acos(sin(rlat1)*sin(rlat2)+
cos(rlat1)*cos(rlat2)*cos(rlon2-rlon1)));
}
int main(int argc, char** argv) {
nearest_distance(6367.47,10,64,10,64);
return 0;
}
Now, the value of 'a' after the calculation is reported as being '1'. And, on this AIX machine, it looks like 1 > 1 is true as my 'if' is entered !!! And my acos of what I think is '1' returns NanQ since 1 is bigger than 1. May I ask how that is even possible ? I do not know what to think anymore !
The code works just fine on other architectures where 'a' really takes the value of what I think is 1 and acos(a) is 0.
If you do a comparison where result and expctedResult are float types:
if (result == expectedResult)
Then it is unlikely that the comparison will be true. If the comparison is true then it is probably unstable – tiny changes in the input values, compiler, or CPU may change the result and make the comparison be false.
Comparing with epsilon – absolute error
if (fabs(result - expectedResult) < 0.00001)
From Comparing floating point numbers
What Every Computer Scientist Should Know About Floating-Point Arithmetic
Print out the bits. You might just be getting fooled by some rounding error in the display of the floats as decimal real numbers.
The printf function, without a specified precision, will only show you the first 6 digits. So, try printing with a higher degree of precision... it is possible that a is slightly larger than 1, but only by a little. If you want to make things more robust, instead of (a>1), you can use (a-1)>epsilon for some value of epsilon.
1.000000000000000000001 is greater than 1. Are you sure you just aren't see enough decimal places? If that check is passing I'd wager thats your issue.
The usual solution is to use some form of epsilon to stop you worrying about rounding errors. ie if the double you have ought to be then try doing
if ( a > 1.00001f )
Its probably close enough to one so as not to cause you problems :)
Related
Is there any way to ensure that a floating-point variable entered by the user, having 2 decimal places after the decimal point, retains its exact value, rather than losing precision?
This is the example case:
I want to round a float with 50 numbers after radix point, like this
Before rounding = 0.70999997854232788085937500000000000000000000000000
to this:
After rounding = 0.71000000000000000000000000000000000000000000000000
I became confused when I wanted to compare a float number in a condition like this:
== Program Start==
Input : 0.71
/* program logic */
if (input == 0.71) {
printf("True !");
} else {
printf("False !");
}
Output : False !
==Program End==
The output was False ! and will always be False ! because the true value of user's input is 0.70999997854232788085937500000000000000000000000000, and not 0.71000000000000000000000000000000000000000000000000
Is there any way to round a float value like that? I read about the potential for inaccuracies with floating point here:
Why Are Floating Point Numbers Inaccurate?
and followed it to these links: Is there a function to round a float in C or do I need to write my own?
and Rounding Number to 2 Decimal Places in C
However, these don't answer my question. If I use ceilf(input * 100) / 100 function, it will make the input 0.71 into 0.71000 when printf()d using %.5f format - which seems to work. But when I print with %.50f, the real input value appears as 0.709999978542327880859375. So, I can't compare to that value in my condition.
So, if floating point can never be accurate, what is the trick for the program logic above to get a true return value at that condition?
All of the user's input comes in as text. The easiest -- and, possibly, safest -- way to check it is to compare it as a string before even converting to number:
if (strcmp("0.71", input) == 0) {
printf("True !");
} else {
printf("False !");
}
Of course, this may not be acceptable to you, if you wish to check for something other than equality :)
The other point is that you are interested in fixed, rather than floating numbers here -- but are confusing them with actual integers. If hundredths is what you'd like to work with, then work with the integer numbers of hundredths... For example, consider money -- instead of using float (or double) to store the amounts of dollars (like $7.61), use int (or, god bless you, long) to store cents (like ¢761).
Similarly, for another example, if you are counting time and need precision of one thousandth of a second, then use integer numbers of milliseconds, instead of floating-point number of seconds.
This will sidestep your entire problem altogether and may also make your programs faster...
I'm sure this question has been answered before, however:
float rounded_down = floorf(input * 100) / 100; /* Result: 0.70 */
float nearest = roundf(input * 100) / 100; /* Result: 0.71 */
float rounded_up = ceilf(input * 100) / 100; /* Result: 0.71 */
The library this functions belongs I think is math.h.
You can test equality with a range as you've experienced.
Just rewrite your equality test with:
if(input <= .71 + EPSILON && input >= .71 - EPSILON) {
}
Here you can create your own EPSILON based on your tolerance, or you can perhaps use FLT_EPSILON from #include<cfloat> for C++ or #include <float.h> in C.
Recall that floats do not have 50 digits of decimal precision. So trying to round at the 50th decimal place isn't going to work out so well. Floats have about 6 (sometimes more) digits of precision.
This question already has answers here:
Comparing float and double
(3 answers)
Closed 7 years ago.
int main(void)
{
float me = 1.1;
double you = 1.1;
if ( me == you ) {
printf("I love U");
} else {
printf("I hate U");
}
}
This prints "I hate U". Why?
Floats use binary fraction. If you convert 1.1 to float, this will result in a binary representation.
Each bit right if the binary point halves the weight of the digit, as much as for decimal, it divides by ten. Bits left of the point double (times ten for decimal).
in decimal: ... 0*2 + 1*1 + 0*0.5 + 0*0.25 + 0*0.125 + 1*0.0625 + ...
binary: 0 1 . 0 0 0 1 ...
2's exp: 1 0 -1 -2 -3 -4
(exponent to the power of 2)
Problem is that 1.1 cannot be converted exactly to binary representation. For double, there are, however, more significant digits than for float.
If you compare the values, first, the float is converted to double. But as the computer does not know about the original decimal value, it simply fills the trailing digits of the new double with all 0, while the double value is more precise. So both do compare not equal.
This is a common pitfall when using floats. For this and other reasons (e.g. rounding errors), you should not use exact comparison for equal/unequal), but a ranged compare using the smallest value different from 0:
#include "float.h"
...
// check for "almost equal"
if ( fabs(fval - dval) <= FLT_EPSILON )
...
Note the usage of FLT_EPSILON, which is the aforementioned value for single precision float values. Also note the <=, not <, as the latter will actually require exact match).
If you compare two doubles, you might use DBL_EPSILON, but be careful with that.
Depending on intermediate calculations, the tolerance has to be increased (you cannot reduce it further than epsilon), as rounding errors, etc. will sum up. Floats in general are not forgiving with wrong assumptions about precision, conversion and rounding.
Edit:
As suggested by #chux, this might not work as expected for larger values, as you have to scale EPSILON according to the exponents. This conforms to what I stated: float comparision is not that simple as integer comparison. Think about before comparing.
In short, you should NOT use == to compare floating points.
for example
float i = 1.1; // or double
float j = 1.1; // or double
This argument
(i==j) == true // is not always valid
for a correct comparison you should use epsilon (very small number):
(abs(i-j)<epsilon)== true // this argument is valid
The question simplifies to why do me and you have different values?
Usually, C floating point is based on a binary representation. Many compilers & hardware follow IEEE 754 binary32 and binary64. Rare machines use a decimal, base-16 or other floating point representation.
OP's machine certainly does not represent 1.1 exactly as 1.1, but to the nearest representable floating point number.
Consider the below which prints out me and you to high precision. The previous representable floating point numbers are also shown. It is easy to see me != you.
#include <math.h>
#include <stdio.h>
int main(void) {
float me = 1.1;
double you = 1.1;
printf("%.50f\n", nextafterf(me,0)); // previous float value
printf("%.50f\n", me);
printf("%.50f\n", nextafter(you,0)); // previous double value
printf("%.50f\n", you);
1.09999990463256835937500000000000000000000000000000
1.10000002384185791015625000000000000000000000000000
1.09999999999999986677323704498121514916420000000000
1.10000000000000008881784197001252323389053300000000
But it is more complicated: C allows code to use higher precision for intermediate calculations depending on FLT_EVAL_METHOD. So on another machine, where FLT_EVAL_METHOD==1 (evaluate all FP to double), the compare test may pass.
Comparing for exact equality is rarely used in floating point code, aside from comparison to 0.0. More often code uses an ordered compare a < b. Comparing for approximate equality involves another parameter to control how near. #R.. has a good answer on that.
Because you are comparing two Floating point!
Floating point comparison is not exact because of Rounding Errors. Simple values like 1.1 or 9.0 cannot be precisely represented using binary floating point numbers, and the limited precision of floating point numbers means that slight changes in the order of operations can change the result. Different compilers and CPU architectures store temporary results at different precisions, so results will differ depending on the details of your environment. For example:
float a = 9.0 + 16.0
double b = 25.0
if(a == b) // can be false!
if(a >= b) // can also be false!
Even
if(abs(a-b) < 0.0001) // wrong - don't do this
This is a bad way to do it because a fixed epsilon (0.0001) is chosen because it “looks small”, could actually be way too large when the numbers being compared are very small as well.
I personally use the following method, may be this will help you:
#include <iostream> // std::cout
#include <cmath> // std::abs
#include <algorithm> // std::min
using namespace std;
#define MIN_NORMAL 1.17549435E-38f
#define MAX_VALUE 3.4028235E38f
bool nearlyEqual(float a, float b, float epsilon) {
float absA = std::abs(a);
float absB = std::abs(b);
float diff = std::abs(a - b);
if (a == b) {
return true;
} else if (a == 0 || b == 0 || diff < MIN_NORMAL) {
return diff < (epsilon * MIN_NORMAL);
} else {
return diff / std::min(absA + absB, MAX_VALUE) < epsilon;
}
}
This method passes tests for many important special cases, for different a, b and epsilon.
And don't forget to read What Every Computer Scientist Should Know About Floating-Point Arithmetic!
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
C compiler bug (floating point arithmetic)?
I've got two doubles which I can guarantee are exactly equal to 150 decimal places - ie. the following code:
printf("***current line time is %5.150lf\n", current_line->time);
printf("***time for comparison is %5.150lf\n", (last_stage_four_print_time + FIVE_MINUTES_IN_DAYS));
...returns:
***current line time is 39346.526736111096397507935762405395507812500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
***time for comparison is 39346.526736111096397507935762405395507812500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
FIVE_MINUTES_IN_DAYS is #defined, and current_line->time and last_stage_four_print_time are both doubles.
My problem is that the next line of my debugging code:
printf("if condition is %d\n", (current_line->time >= (last_stage_four_print_time + FIVE_MINUTES_IN_DAYS)));
returns the following:
if condition is 0
Can anyone tell me what's going on here? I am aware of the non-decimal/inexact nature of floats and doubles but these are not subject to any error at all (the original figures have all been read with sscanf or #defined and are all specified to 10 decimal places).
EDIT: My mistake was assuming that printf-ing the doubles accurately represented them in memory, which was wrong because one value is being calculated on-the-fly. Declaring (last_stage_four_print_time + FIVE_MINUTES_IN_DAYS) as threshold_time and using that instead fixed the problem. I will make sure to use an epsilon for my comparisons - I knew that was the way to go, I was just confused as to why these values which I (incorrectly) thought looked the same were apparently inequal.
Floats certainly are not accurate to 150 significant digits, so I 'm not sure what conclusion can be drawn from the "visual" comparison (if any).
On the other hand, the values are obviously not bit-identical (and how could they be, since one of them is calculated on the spot with addition?). So it's not really clear why the behavior you see is unexpected.
Don't ever compare floats like that, just do the standard comparison of difference vs epsilon.
Read about floating point representation (particularly http://en.wikipedia.org/wiki/IEEE_754-2008). Try printing the actual contents of the bytes containing the doubles as hexadecimal and they won't match bit for bit.
The proper comparison for floats is in Knuth (Seminumerical algorithms). Simply (replace bool with int and float with double, true with 1):
bool almostEqual(float x, float y, float epsilon)
{
if (x == 0.0 && y == 0.0) {
return true;
}
if (fabs(x) > fabs(y)) {
return fabs((x - y) / x) < epsilon;
} else {
return fabs((x - y) / y) < epsilon;
}
}
You should always use an EPSILON value for comparison of floats and doubles to check for equality. Even though it looks the same the internal representation is not guaranteed to match because of the way these types of numbers are represented in binary.
You can do something like
#define EPSILON 0.00001
...
if (fabs(a - b) <= EPSILON) return 1; // they are equal
return 0;
Jesus is right about how to solve this.
As for why... in one case you read in a constant value, in the other case you perform an addition operation. Even if the printed output is exactly the same, the binary representation can be slightly different.
Try inspecting the memory backing the two double's and see if any bits are different (there will be differences).
For a comprehensive treatment, I recommend
http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
In general you shouldn't use == to compare floats or doubles. You should instead check that the difference is smaller than some small number.
double second_number = last_stage_four_print_time + FIVE_MINUTES_IN_DAYS;
if (fabs(current_line->time - second_number) < 0.001 || current_line->time > second_number){
// your comparison code
}
First, doubles have just 15-16 decimal places (log_2 of 52 bit matissa).
Second, if you want to compare, use the already mentioned epsilon.
Thirdly, for debugging, print the hex value.
I've written an iPhone-App and encountered a problem concerning typecasting between float and int. I've rewritten the code in C and the results always were the same, no matter if having it compiled under OS X (Console and Xcode), Linux (Console) or Windows (Visual Studio):
// Calculation of a page index depending on the amount of pages, its x-offset on the view
// and the total width of the view
#include <stdio.h>
int main()
{
int result = 0;
int pagesCnt = 23;
float offsetX = 2142.0f;
float width = 7038.0f;
offsetX = offsetX / width;
offsetX = (float)pagesCnt * offsetX;
result = (int)offsetX;
printf("%f (%d)\n", offsetX, result);
// The console should show "7.000000 (7)" now
// But actually I read "7.000000 (6)"
return 0;
}
Of course, we have a loss of precision here. When doing the math with the calculator x results in 7.00000000000008 and not in just 7.000000.
Nevertheless, as much as I understand C, this shouldn't be a problem as C is meant to truncate the the after-point-positions of a floating point number when converting it to an integer. In this case this is what I want actually.
When using double instead of float, the result would be as expected, but I don't need double precision here and it shouldn't make any difference.
Am I getting something wrong here? Are there situations when I should avoid conversion to int by using (int)? Why is C decrementing result anyway? Am I supposed to always use double?
Thanks a lot!
Edit: I've misformulated something: Of course, it makes a difference when using double instead of float. I meant, that it shouldn't make a difference to (int) 7.000000f or 7.00000000000008.
Edit 2: Thanks to you I understand my mistake now. Using printf() without defining the floating point precision was wrong. (int)ing 6.99... to 6 is correct, of course. So, I'll use double in the future when encountering problems like this.
When I augment the precision for the output, the result that I receive from your program is 6.99999952316284179688 (6), so 6 seems to be correct.
If you change printf("%f (%d)\n", offsetX, result); to printf("%.8f (%d)\n", offsetX, result); you will see the problem. After making that change, the output is:
6.99999952 (6)
You can correct this by rounding instead of casting to int. That is, change result = (int)offsetX; to result = roundf(offsetX);. Don't forget to #include <math.h>. Now, the output is:
6.99999952 (7)
The compiler is not free to change the order of floating-point operations in many cases, since finite precision arithmetic is not, in general, associative. i.e.,
(23 * 2142) / 7038 = 7.00000000000000000000
(2142 / 7038) * 23 = 6.99999999999999999979
These aren't single precision results, but it shows that double precision will not address your problem either.
If have the following C function, used to determine if one number is a multiple of another to an arbirary tolerance
#include <math.h>
#define TOLERANCE 0.0001
int IsMultipleOf(double x,double mod)
{
return(fabs(fmod(x, mod)) < TOLERANCE);
}
It works fine, but profiling shows it to be very slow, to the extent that it has become a candidate for optimization. About 75% of the time is spent in modulo and the remaining in fabs. I'm trying to figure a way of speeding things up, using something like a look-up table. The parameter x changes regularly, whereas mod changes infrequently. The number of possible values of x is small enough that the space for a look-up would not be an issue, typically it will be one of a few hundred possible values. I can get rid of the fabs easily enough, but can't figure out a reasonable alternative to the modulo. Any ideas on how to optimize the above?
Edit The code will be running on a wide range of Windows desktop and mobile devices, hence processors could include Intel, AMD on desktop, and ARM or SH4 on mobile devices. VisualStudio 2008 is the compiler.
Do you really have to use modulo for this?
Wouldn't it be possible to just result = x / mod and then check if the decimal part of result is close to 0. For instance:
11 / 5.4999 = 2.000003 ==> 0.000003 < TOLERANCE
Or something like that.
Division (floating point or not, fmod in your case) is often an operation where the execution time varies a lot depending on the cpu and compiler:
gcc has a builtin replacement for
that if you give it the right compile
flags or if you use __builtin_fmod
explicitly. This then might map the
operation on a small number of
assembler instructions.
there may be special units like SSE
on intel processors where this
operation is implemented more
efficiently
By such tricks, depending on your environment (you didn't tell which) the time may vary from some clock cycles to some hundred. I think best is to look into the documentation of your compiler and cpu for that particular operation.
The following is probably overkill, and sub-optimal. But for what it is worth here is one way on how to do it.
We know the format of the double ...
1 bit for the sign
11 bits for the biased exponent
52 fraction bits
Let ...
value = x / mod;
exp = exponent bits of value - BIAS;
lsb = least sig bit of value's fraction bits;
Once you have that ...
/*
* If applying the exponent would eliminate the fraction bits
* then for double precision resolution it is a multiple.
* Note: lsb may require some massaging.
*/
if (exp > lsb)
return (true);
if (exp < 0)
return (false);
The only case remaining is the tolerance case. Build your double so that you are getting rid of all the digits to the left of the decimal.
sign bit is zero (positive)
exponent is the BIAS (1023 I think ... look it up to be sure)
shift the fraction bits as appropriate
Now compare it against your tolerance.
I think you need to inspect the bowels of your C RTL fmod() function: X86 FPU's have 'FPREM/FPREM1' instructions which computes remainders by repeated subtraction.
While floating point division is a single instruction, it seems you may need to call FPREM repeatedly to get the right answer for modulus, so your RTL may not use it.
I have not tested this at all, but from the way I understand fmod this should be equivalent inlined, which might let the compiler optimize it better, though I would have thought that the compiler's math library (or builtins) would work just as well. (also, I don't even know for sure if this is correct).
#include <math.h>
int IsMultipleOf(double x, double mod) {
long n = x / mod; // You should probably test for /0 or NAN result here
double new_x = mod * n;
double delta = x - new_x;
return fabs(delta) < TOLERANCE; // and for NAN result from fabs
}
Maybe you can get away with long long instead of double if you have comparable scale of data. For example long long would be enough for over 60 astronomical units in micrometer resolution.
Does it need to be double precision ? Depending on how good your math library is, this ought to be faster:
#include <math.h>
#define TOLERANCE 0.0001f
bool IsMultipleOf(float x, float mod)
{
return(fabsf(fmodf(x, mod)) < TOLERANCE);
}
I presume modulo looks a little like this on the inside:
mod(x,m) {
while (x > m) {
x = x - m
}
return x
}
I think that through some sort of search i could be optimised: eg:
fastmod(x,m) {
q = 1
while (m * q < x) {
q = q * 2
}
return mod((x - (q / 2) * m), m)
}
You might even choose to replace the finall call to mod with annother call to fastmod, adding the condition that if x < m then to return x.