This question already has answers here:
Why the control goes in “else” part? [duplicate]
(8 answers)
Closed 8 years ago.
Today I was playing with floating-point number in C
code likes:
float a = 0.0;
a += 0.8;
if(a == 0.800000)
printf("correct");
The if statement do not get executed and for this I printed the value of a which was 0.800000.
void main(){
float a=0.0f;
a=a+0.1f;
if(a==0.1f)
printf( "1correct");
a += 0.1f;
if(a==0.2f)
printf( "2correct");
a += 0.1f;
if(a==0.3f)
printf( "3correct");
a += 0.1f;
if(a==0.4f)
printf( "4correct");
if(a==0.5f)
printf( "5correct");
a += 0.1f;
if(a==0.6f)
printf( "6correct");
a += 0.1f;
if(a==0.7f)
printf( "7correct");
a += 0.1f;
if(a==0.8f)
printf( "8correct");
}
The following program prints output as :
1correct2correct3correct4correct5correct6correct
the statement 7correct and 8correct are not being printed out.
Any one please can explain Brief here!!
There are many decimal numbers that cannot be precisely represented with a finite number of binary digits.
In general, it's a bad idea to test floats or doubles for exact equality. If you really want to test them, check that they fit within a small range:
if ( a > 0.799999 && a < 0.800001 )
printf( "correct" );
Whenever you can possibly use integers rather than floats or doubles, do so. For example don't use a float for a loop counter or array index.
There are lots of good uses for floating point, such as modeling physical phenomena, predicting the weather and so on, but floating point has many subtleties.
Because floating-point numbers can lose in precision because of maximum error value, you must check for a small range and not equality.
Take a look here and here for more.
Related
This question already has answers here:
Why are floating point numbers inaccurate?
(5 answers)
Closed 5 years ago.
I am a beginner and this is (a simplified version of) part of a code I am writing:
1.prompt user to input a number (float dollar amount), lets say user will only key in amount which are multiples of 0.05 ;
2.calculate the (int)number of nickels in that dollar amount.
int main(void)
{
float amount = 0;
printf("$ ");
amount = get_float();
int n = 0;
while ((amount - 0.05) >= 0)
{
amount -= 0.05;
n ++;
}
printf("%i nickels\n", n);
}
It works for any amount <=0.3 or >=1.2 (so $2 has 40 nickels, and $0.30 has 6 nickels);
but one nickel less for any amount between/including 0.35 and 1.15 (so $0.35 has 6 nickels, and $1 has 19 nickels)
I did step by step printing, and it turns out that for any amount between 0.35 and 1.15, the program stops at the last 0.050000, instead of going back to the loop and loop it one last time.
What went wrong? Please help... Thanks so much for your time!
You are hitting up against floating point rounding.
Floating points are never exactly accurate, try calculating
printf("one third 'ish' = %6.20lf\n", (double) 1.0/ (double) 3.0);
Look at the answer, it's not quite accurate. :)
Your best bet is to accept the input, convert it to an integer (ie, cents) by multiplying by 100, removing any decimals using round() and assigning to a long.
#include <math.h> // to get the round() function
.
.
.
long amountInCents = round(amount * 100);
Then, change your code to compare against 5 cents, not $0.05, and to reduce by 5 cents, not $0.05
This way, you get rid of all 'rounding' issues.
EDIT: cmaster showed me that using floor() didn't work, using $0.57 as input, when using 'double' variables (not float), $0.57 converted to (long) 56! He supplied code and I couldn't believe my eyes!
The is no bug in your code in the strictest sense as the underlying reasoning is correct; however note that the value 0.35 cannot be represented exactly in the float datatype, the same holds for 0.05; as the division (what basically is the sematics of the code in the question) is implemented via repeated subtraction, the error caused by the inability to exactly represent the desired values accumulates. The result is that the number of subtractions is different from the analytically expected result, as the termination condition is reached too soon. The float datatype is not suitable for financial calculations, even in such a very small everyday example.
This is terrible, but it is a matter of fact.
I found a fix. This is working
enter code here
while ((amount - 0.0499) >= 0)
{
amount -= 0.05;
n ++;
}
while scanning .35 amount as float the actual amount value is 0.3499
This question already has answers here:
Is floating point math broken?
(31 answers)
Closed 6 years ago.
I tried to sum some numbers in a for loop but it didn't go as I expected
float sum = 0;
int i;
printf("0.1+0.1=%f\n", 0.1 + 0.1);
for (i = 0; i<1000000; i++)
{
sum = sum + 0.1;
}
printf("the sum need to be 100000 \n");
printf("the real sum is:\n %f\n", sum);
system("PAUSE");
this program prints:
0.1+0.1=0.200000
the sum need to be 100000
the real sum is:
100958.343750
Press any key to continue . . .
can you explain please this strange result?
the international standard for floating point numbers does not have an exact representation for some decimal numbers.
http://en.wikipedia.org/wiki/IEEE_754
It is due to the way they are stored in memory, the way the mantissa and exponent are stored.
https://en.wikipedia.org/wiki/Floating_point
This is also the reason why you should never compare two float numbers even if they look "the same".
I still remember how surprised I was the fist time a simple code comparing two float numbers didn't work :) This alone would open a dedicated universe of discussions. It is very worth reading anyway:
http://floating-point-gui.de/errors/comparison/
The floating numbers are stored in memory as x*2^y where x is between 0 and 1 with some precision and y is integer and so they accurately don't represent most numbers, they represent numbers "close enough".
When you do this addition multiple times, the error is just more visible.
You can use double type for better accuracy.
This question already has answers here:
Checking if float is an integer
(8 answers)
Closed 8 years ago.
I have a program in which i need to print FLOAT in case of a float number or print INTEGER in case of a regular number.
for Example pseudo code
float num = 1.5;
if (num mod sizeof(int)==0)
printf ("INTEGER");
else
printf("FLOAT");
For example:
1.6 would print "FLOAT"
1.0 would print "INTEGER"
Will something like this work?
All float types have the same size, so your method won't work. You can check if a float is an integer by using ceilf
float num = 1.5;
if (ceilf(num) == num)
printf ("INTEGER");
else
printf("FLOAT");
You can use modff():
const char * foo (float num) {
float x;
modff(num, &x);
return (num == x) ? "INTEGER" : "FLOAT";
}
modff() will take a float argument, and break it into its integer and fractional parts. It stores the integer part in the second argument, and the fractional part is returned.
The "easy" way, but with a catch:
You could use roundf, like this:
float z = 1.0f;
if (roundf(z) == z) {
printf("integer\n");
} else {
printf("fraction\n");
}
The problem with this and other similar techniques (such as ceilf) is that, while they work great for whole number constants, they will fail if the number is a result of a calculation that was subject to floating-point round-off error. For example:
float z = powf(powf(3.0f, 0.05f), 20.0f);
if (roundf(z) == z) {
printf("integer\n");
} else {
printf("fraction\n");
}
Prints "fraction", even though (31/20)20 should equal 3, because the actual calculation result ended up being 2.9999992847442626953125.
So how do we deal with this?
Any similar method, be it fmodf or whatever, is subject to this. In applications that perform complex or rounding-prone calculations, usually what you want to do is define some "tolerance" value for what constitutes a "whole number" (this goes for floating-point equality comparisons in general). We often call this tolerance epsilon. For example, lets say that we'll forgive the computer for up to +/- 0.00001 rounding error. Then, if we are testing z, we can choose an epsilon of 0.00001 and do:
if (fabsf(roundf(z) - z) <= 0.00001f) {
printf("integer\n");
} else {
printf("fraction\n");
}
You don't really want to use ceilf here because e.g. ceilf(1.0000001) is 2 not 1, and ceilf(-1.99999999) is -1 not -2.
Choose a tolerance value that is appropriate for your application. For more information, check out this article on comparing floating-point numbers.
Will something like this work?
No. For example on the x86_32 and ARM 32 bit architectures sizeof(int) == 4 and sizeof(float) == 4.
Also whatever you think mod is, it clearly shows you don't understand what the sizeof operator does.
This question already has answers here:
Floating point inaccuracy examples
(7 answers)
C++ floating point precision [duplicate]
(5 answers)
Closed 8 years ago.
I found this code snippet on Page 174, A Book on C -Al Kelley, Ira Pohl .
int main()
{
int cnt=0; double sum=0.0,x;
for( x=0.0 ;x!= 9.9 ;x+=0.1)
{
sum=sum +x;
printf("cnt = %5d\n",cnt++);
}
return 0;
}
and it became a infinite loop as the book said it would. It didnt mention the precise reason except saying that it had to do with the accuracy of the machine.
I modified the code to check if
x=9.9
would ever become true, i.e. x was attaining 9.9 by adding the following lines
diff=x-9.9;
printf("cnt =10%d \a x =%10.10lf dif=%10.10lf \n",++cnt,x,diff);
and i got the following lines among the output
cnt =1098 x =9.7000000000 dif=-0.2000000000
cnt =1099 x =9.8000000000 dif=-0.1000000000
cnt =10100 x =9.9000000000 dif=-0.0000000000
cnt =10101 x =10.0000000000 dif=0.1000000000
cnt =10102 x =10.1000000000 dif=0.2000000000
if x is attaining the value 9.9 exactly , why is it still a infinite loop?
You are simply printing the number with too poor accuracy to notice that it isn't exact. Try something like this:
#include <stdio.h>
int main()
{
double d = 9.9;
if(d == 9.9)
{
printf("Equal!");
}
else
{
printf("Not equal! %.20f", d);
}
}
Output on my machine:
Not equal! 9.90000000000000035527
The book is likely trying to teach you to never use == or != operators to compare floating point variables. Also for the same reason, never use floats as loop iterators.
The problem is that most floating point implementation are based on IEEE 754. See http://en.wikipedia.org/wiki/IEEE_floating_point
The problem with this is, that numbers are builded with base 2 (binary formats).
The number 9.9 can never be build with base 2 excatly.
The "Numerical Computation Guide" by David Goldberg gves an exact statement about it:
Several different representations of real numbers have been proposed,
but by far the most widely used is the floating-point representation.
Floating-point representations have a base b (which is always assumed to
be even) and a precision p. If b = 10 and p = 3, then the number 0.1 is
represented as 1.00 × 10^-1. If b = 2 and p = 24, then the decimal
number 0.1 cannot be represented exactly, but is approximately
1.10011001100110011001101 × 2^-4.
You can safely assume two floating point numbers are never equal 'exactly' (unless one is a copy of the other).
Computer works on binary and floating point, in other words in base 2. Just like base 10, base 2 have numbers that it cannot build. For example, try to write the fraction 10/3 in base 10. You'll end up with infinite 3s. and in Binary, you cannot even write 0.1 (decimal) in binary, you'll also get a recurring pattern 0.0001100110011... (binary).
This video will do better to explain http://www.youtube.com/watch?v=PZRI1IfStY0
I edited a C program for my assignment, previously there wasn't typecasting and the iteration stopped at i=1, now with the typecasting it stops at i=6.
Any ideas why? Thanks in advance!
int main(void)
{
int i = 0;
double d = 0.0;
while ( (i == (int) (d * 10)) && (i < 10) )
{
i = i + 1;
d = (double) (d + 0.1);
printf("%d %lf\n", i, d);
}
printf("%d %lf\n", i, d);
getch();
return 0;
}
Floating point arithmetic is inexact. The value 0.1 is not exactly representable in binary floating point. The recommended reading here is: What Every Computer Scientist Should Know About Floating-Point Arithmetic.
At some point in the program, d becomes slightly less than i/10 due to rounding error, and so your loop terminates.
In addition to the other answers, I'd like to answer the question why the loop terminates earlier with the condition i == (d * 10) than with i == (int) (d * 10).
In the first case, int value at the left side of == is promoted to double, so the inequality happens when the accumulated error in d*10 is either positive or negative (e.g. 0.999999 or 1.000001).
In the 2nd case, the right side is truncated to int, so the inequality happens only when the error is negative (e.g. 5.999999). Therefore, the 1st version would fail earlier.
As has been stated many times before, the reason this doesn't work is that binary floating point numbers cannot represent all decimal floating point binary numbers, it just isn't possible. To read more, check out this really great article:
What Every Programmer Should Know About Floating-Point Arithmetic
Now, on the more practical side of things, when using floating point and comparing it to another number, you should almost always round the value or use an epsilon value, like this:
if (ABS(doubleValue - intValue) < 0.00001) // 0.00001 is a margin-of-error for floating point arithmetic
// the two numbers are even (or close to it)