what's is going wrong with this loop condition? [duplicate] - c

This question already has answers here:
How dangerous is it to compare floating point values?
(12 answers)
Closed 9 years ago.
Look at the output of this link(scroll down to see the output) to find out what I'm trying to accomplish
The problem is with the for loop on line number 9-11
for(i=0; i<=0.9; i+=0.1){
printf("%6.1f ",i);
}
I expected this to print values from 0.0 until 0.9 but it stops after printing 0.8, any idea why ??

Using float here is source of problem. Instead, do it with an int:
int i;
for(i = 0; i <= 10; i++)
printf("%6.1f ", (float)(i / 10.0));
Output:
0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0

Ideally floating point should not be used for iteration, but if you want to know why change your code and see how.
for(float i=0; i<=0.9f; ){
i+=0.1f;
System.out.println(i);
}
Here is the result.
0.1
0.2
0.3
0.4
0.5
0.6
0.70000005
0.8000001
0.9000001
your 9th value exceeds 0.9.

Floating point arithmetic is inexact in computing. This is because of the way that a computer represents floating point values. Here's an excerpt from an MSDN article on the subject:
Every decimal integer can be exactly represented by a binary integer; however, this is not >true for fractional numbers. In fact, every number that is irrational in base 10 will also be >irrational in any system with a base smaller than 10.
For binary, in particular, only fractional numbers that can be represented in the form p/q, >where q is an integer power of 2, can be expressed exactly, with a finite number of bits.
Even common decimal fractions, such as decimal 0.0001, cannot be represented exactly in >binary. (0.0001 is a repeating binary fraction with a period of 104 bits!)
Link to the full article: https://support.microsoft.com/kb/42980

Floating point number cannot precisely represent decimals, so rounding errors accumulate:
#include <iostream>
#include <iomanip>
using namespace std;
int main() {
float literal = 0.9;
float sum = 0;
for(int i = 0; i < 9; i++)
sum += 0.1;
cout << setprecision(10) << literal << ", " << sum << endl;
return 0;
}
Output:
0.8999999762, 0.9000000954

You loop is right, but the float comparison in loops is not safe.
The problem is that a binary floating point number cannot exactly represent 0.1
This would work.
for(i=0.0; i<=0.9001; i+=0.1){
printf("%6.1f ",i);

Related

Print arithmetic progression below a number [duplicate]

This question already has answers here:
Is floating point math broken?
(31 answers)
Closed 10 months ago.
I have this code and I want to print all the numbers of an arithmetic progression of ratio 0.3 but when I use the following code it includes 3, when I wanted all non-negative below 3. What would be another way to do it?
#include <stdio.h>
int main() {
double x = 0;
while(x < 3.0) {
printf("x = %f\n", x);
x += 0.3;
}
return 0;
}
3/10 is a periodic number in binary just like 1/3 is a periodic number in decimal. As such, it can't be accurately represented by a floating point number.
$ perl -e'printf "%.100g\n", 0.3'
0.299999999999999988897769753748434595763683319091796875
(Used Perl here because it was terser. The choice of language isn't important because it's a property of floating point numbers, not the language.)
In your case, the problem can be avoided by scaling the numbers up by a factor of ten.
#include <stdio.h>
int main() {
int x = 0;
while(x < 30) {
printf("x = %f\n", x/10.0);
x += 3;
}
return 0;
}

equality of two float numbers in for loop [duplicate]

This question already has answers here:
Is floating point math broken?
(31 answers)
Closed 5 years ago.
What I am trying to do here is, I am taking a precision value (less than 1) and printing count of all the numbers of type 1/n (n is natural number) which are greater than or equal to the precision value (input).
#include <stdio.h>
int main(){
int i=1,terms=0;
float n;
printf("Enter precision value : ");
scanf("%f",&n);
while(i>0){
if ((1.0/i) >= n){
printf("%f\n",1.0/i);
sum = sum + (1.0/i);
terms++;
i++;
}
else
break;
}
printf("number of terms : %d\n",terms);
return 0;
}
But if I give input 0.1 than the count (output) is showing only 9. but it should show 10 (it is not including 1/10).
I was using a for loop before and I know that breaking a loop with an if-else statement is not the best thing.
That's just the way math works with limited precision. For example, say you're using six digits of decimal precision. The best you can do for one-third is 0.333333 and the best you can do for 2/3 is 0.666667, but then 2 * 1/3 will not equal 2/3. And 3 * 1/3 will not equal 1. But 1/3 + 2/3 will.
Just as 1/3 cannot be expressed exactly in decimal, 0.1 cannot be expressed exactly in binary. So testing for equivalence is not smart.

Comparison of a float with a value in C [duplicate]

This question already has answers here:
strange output in comparison of float with float literal
(8 answers)
Closed 5 years ago.
I have come across two programs in C, both comparing floating point number but with different outputs.
1)
#include<stdio.h>
int main()
{
float x = 0.1;
if (x == 0.1)
printf("IF");
else if (x == 0.1f)
printf("ELSE IF");
else
printf("ELSE");
}
Output : ELSE IF
2)
int main()
{
float x = 0.5;
if (x == 0.5)
printf("IF");
else if (x == 0.5f)
printf("ELSE IF");
else
printf("ELSE");
}
Output : IF
why 0.5 is not promoted to double whereas 0.1 is?
Since double is wider than float, x == 0.1 is interpreted as (double) x == 0.1.
This works for 0.5 because 0.5 is exactly representable in binary, so (double) 0.5f produces precisely 0.5. On the other hand, 0.1 has an infinite-digit representation in binary, and 0.1f and 0.1 end up being rounded to numbers that differ in how many initial digits of the sequence they hold.
In an analogy with decimal numbers, you can think of the above situation as trying to write down the fraction 1/3 by rounding it to a fixed number of decimal digits. Using a 5-significant-digit representation, you get 0.33333; choosing a 10-digit one results in 0.3333333333. Now, "casting" the five-digit number to ten digits results in 0.3333300000, which is a different number than 0.3333333333. In the same analogy, 0.5 in is like 1/10 in decimal, which would be represented as 0.10000 and 0.1000000000 respectively, so one could convert it to the other representation and back without changing its meaning.
If the contents of x is a marker value set from code, then simply compare it to 0.1f instead of to 0.1. If it is the result of a calculation, see Paul's answer for the correct way to compare floating-point quantities.
The proper way of comparing one floating point number with another is by using a precission value, for example
#define EPS 0.00001
#define ABS(a) ((a)<0?-(a):(a))
if (ABS(a-b)<EPS)
...
This is derived from:
if (a == b) // "equal" of fp numbers is not well defined
if (a-b == 0) // so comparing with zero is also ill defined
if (ABS(a-b) < EPS) // and so we compare with this small precission

Looping over a range of floats in C

I am trying to write a program in C to accomplish the following task.
Input: Three double-precision numbers, a, b, and c.
Output: All the numbers from b to a, that can be reached by decrements of c.
Here is a simple program (filename: range.c).
#include <stdlib.h>
#include <stdio.h>
int main()
{
double high, low, step, var;
printf("Enter the <lower limit> <upperlimit> <step>\n>>");
scanf("%lf %lf %lf", &low, &high, &step);
printf("Number in the requested range\n");
for (var = high; var >= low; var -= step)
printf("%g\n", var);
return 0;
}
However, the for loop behaves rather bizarrely for some inputs. For instance, the following.
10-236-49-81:stackoverflow pavithran$ ./range.o
Enter the <lower limit> <upperlimit> <step>
>>0.1 0.9 0.2
Number in the requested range
0.9
0.7
0.5
0.3
10-236-49-81:stackoverflow pavithran$
I cannot figure out why the loop quits at var = 0.1. While for another input, it behaves as expected.
10-236-49-81:stackoverflow pavithran$ ./range.o
Enter the <lower limit> <upperlimit> <step>
>>0.1 0.5 0.1
Number in the requested range
0.5
0.4
0.3
0.2
0.1
10-236-49-81:stackoverflow pavithran$
Had the weird behaviour in the first situation got something to do with numeric precision?
How can I ensure that the range will always contain floor((high - low)/step) + 1 numbers?
I have tried an alternate method of looping over floats, where I scale the loop variables to integers, and print the result of the loop variable divided by the scaling used. But there's perhaps a better way...
Using a double as a counter in a for loop requires very careful consideration. In many instances it's best avoided.
I'm sure you know that not all numbers that are exact in decimal are also exact in binary floating point. In fact, for IEEE754 floating point, only dyadic rationals are. So 0.5 is, but 0.4, 0.3, 0.2, and 0.1 are not.
The closest IEEE754 floating point double to 0.2 is actually the slightly larger 0.200000000000000011102230246251565404236316680908203125.
In your case a repeated subtraction of this from 0.9 eventually causes a number whose first significant figure is a to become a number whose first significant figure is a - 3: your bug then manifests itself.
The simple remedy is to work in integers, decement by 1 each time, and scale your output using step.

C - Summation with Double - Precision

I have problem with precision of double format.
Sample example:
double K=0, L=0, M=0;
scanf("%lf %lf %lf", &K, &L, &M);
if((K+L) <= M) printf("Incorrect input");
else printf("Right, K=%f, L=%f, M=%f", K, L, M);
My test input:
K = 0.1, L = 0.2, M = 0.3 -> Condition but goes to 'else' statement.
How I can correct this difference? Is there any other method to summation?
In the world of Double Precision IEEE 754 binary floating-point format (the ones used on Intel and other processors) 0.1 + 0.2 == 0.30000000000000004 :-) And 0.30000000000000004 != 0.3 (and note that in the marvelous world of doubles, 0.1, 0.2 and 0.3 don't exist as "exact" quantities. There are some double numbers that are very near them, but if you printed them with full precision, they wouldn't be 0.1, 0.2 and 0.3)
To laugh a little, try this: http://pages.cs.wisc.edu/~rkennedy/exact-float
Insert a decimal number and look at the second and third row, it shows how the number is really represented in memory. It's for Delphi, but Double and Single are the same for Delphi and for probably all the C compilers for Intel processors (they are called double and float in C)
And if you want to try for yourself, look at this http://ideone.com/WEL7h
#include <stdio.h>
int main()
{
double d1 = (0.1 + 0.2);
double d2 = 0.3;
printf("%.20e\n%.20e", d1, d2);
return 0;
}
output:
3.00000000000000044409e-01
2.99999999999999988898e-01
(be aware that the output is compiler dependant. Depending on the options, 0.1 + 0.2 could be compiled and rounded to 0.3)
Unlike integer values floating point values are not stored exactly the way you assign values to them. Lets consider the following code:
int i = 1; // this is and always will be 1
float j = 0.03 // this gets stored at least on my machine as something like 0.029999999
Why is this so? Well how many floating point number exist in the interval between 0.1 and 0.2?
An infinite number! So there are values which will get stored as you intended but a hell of a lot of values which will be stored with a small error.
This is the reason why comparing floating point values for equality is not a good idea. Try something like this instead:
float a = 0.3f;
float b = 0.301f;
float threshold = 1e-6;
if( abs(a-b) < threshold )
return true;
else
return false;
There are infinitely many real numbers between any two distinct real numbers. If we were to be able to represent every one of those, we would need infinite memory. Since we only have finite memory, floating point numbers need to be stored with only finite precision. Up to that finite precision, it might be not be true that 0.1 + 0.2 <= 0.3.
Now, you really should go read what's at the other end of the excellent link provided by Paul R.

Resources