While loop involving floating point numbers [duplicate] - c

Why does this program gives no output for float and double datatypes. However, what will be the result when the same code is replaced with for loop??
# include <stdio.h>
int main()
{
float x=1.1;
while (x==1.1)
{
printf("%f\n",x);
x=x-0.1;
}
return 0;
}

float x=1.1;
while (x==1.1)
float and double variables are not capable of storing the exact value of 1.1, only a very close approximation. The exact value in a float and a double will be slightly different due to the difference in precision.
1.1 is a double value. You are storing 1.1 as a double into a float which will slightly alter the value. Then you compare it with the double value 1.1 so it will not quite be equal and so will never enter your condition.
For this to work you need to write 1.1f to ensure that you are working with the same data type everywhere.
In addition I'm sure someone else will explain why comparing floating point values for exact equality is often a bad idea.

Related

VS code is showing different answer for two same code

I run two same code. But it shows different answer.
Code 1:
#include<stdio.h>
int main(){
float far = 98.6;
printf("%f", (far-32)*5/9);
return 0;
}
Code 2:
#include<stdio.h>
int main(){
float far = 98.6;
float cel;
cel = (far-32)*5/9;
printf("%f", cel);
return 0;
}
First code gives 36.99999 as output and second code gives 37.00000 as output.
Research FLT_EVAL_METHOD. This reports the intermediate floating-point math allowed.
printf("%d\n", FLT_EVAL_METHOD);
When this is non-zero, the 2 codes may have different output as printf("%f", (far-32)*5/9); can print the result of (far-32)*5/9 using double or float math.
In the 2nd case, (far-32)*5/9); is performed user float or double and then saved as a float and then printed. Its promotion to a double as part of a printf() ... argument does not affect the value.
For deeper understanding, print far, cel, (far-32)*5/9 with "%a" and "%.17g" for greater detail.
In both cases, far is the float value 0x1.8a6666p+6 or 98.599998474121094...
As I see it the first used double math in printf("%f", (far-32)*5/9); and the second used double math too, yet rounded to a float result from cel = (far-32)*5/9;. To be certain we need to see the intermediate results as suggested above.
Avoid double constants with float objects. It sometimes makes a difference.
// float far = 98.6;
float far = 98.6f;
Use double objects as a default. Save float for select speed/space cases. #Some programmer dude.
The difference lies in the types used and the printf call.
Variable-argument functions like printf will promote arguments of smaller types. So for example a float argument will be promoted to double.
The type double have much higher precision than float.
Since in the first program you do the calculation as part of the actual printf call, not storing the result in a variable using less precision, the compiler might perform the whole calculation using double and increasing the precision. Precision that will be lost when you store the result in cel in the second example.
Unless you have very specific requirements, you should generally always use double for all your floating-point variables and values and calculations.

Strange difference in output for int and float values in C using while loop? [duplicate]

I wrote the following code to compare between a float variable and a double variable in C.
int main()
{
float f = 1.1;
double d = 1.1;
if(f==d)
printf("EQUAL");
if(f < d)
printf("LESS");
if(f > d)
printf("GREATER");
return 0;
}
I am using an online C compiler here to compile my code.
I know that EQUAL will never be printed for recurring decimals. However what I expect should be printed is LESS since double should have a higher precision and therefore should be closer to the actual value of 1.1 than float is. As far as I know, in C when you compare float and double, the mantissa of the float is zero-extended to double, and that zero-extended value should always be smaller.
Instead in all situations GREATER is being printed. Am I missing something here?
The exact value of the closest float to 1.1 is 1.10000002384185791015625. The binary equivalent is 1.00011001100110011001101
The exact value of the closest double to 1.1 is 1.100000000000000088817841970012523233890533447265625. The binary equivalent is 1.0001100110011001100110011001100110011001100110011010.
Lining up the two binary numbers next to each other:
1.00011001100110011001101
1.0001100110011001100110011001100110011001100110011010
The first few truncated bits for rounding to float are 11001100, which is greater than half, so the conversion to float rounded up, making its least significant bits 11001101. That rounding resulted in the most significant difference being a 1 in the float in a bit position that is 0 in the double. The float is greater than the double, regardless of values of bits of lower significance being zero in the float extended to double, but non-zero in the double.
If you'll add the following 2 lines after declaring the 2 variables:
printf("%.9g\n", f);
printf("%.17g\n", d);
you will get the following output:
1.10000002
1.1000000000000001
so it easy to see that due to precision the float is greater then the double thus the printing of GREATER is fine.

Different Answers by removing a printf statement

This is the link to the question on UVa online judge.
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=29&page=show_problem&problem=1078
My C code is
#include <stdio.h>
double avg(double * arr,int students)
{
int i;
double average=0;
for(i=0;i<students;i++){
average=average+(*(arr+i));
}
average=average/students;
int temp=average*100;
average=temp/100.0;
return average;
}
double mon(double * arr,int students,double average)
{
int i;
double count=0;
for(i=0;i<students;i++){
if(*(arr+i)<average){
double temp=average-*(arr+i);
int a=temp*100;
temp=a/100.0;
count=count+temp;
}
}
return count;
}
int main(void)
{
// your code goes here
int students;
scanf("%d",&students);
while(students!=0){
double arr[students];
int i;
for(i=0;i<students;i++){
scanf("%lf",&arr[i]);
}
double average=avg(arr,students);
//printf("%lf\n",average);
double money=mon(arr,students,average);
printf("$%.2lf\n",money);
scanf("%d",&students);
}
return 0;
}
One of the input and outputs are
Input
3
0.01
0.03
0.03
0
Output
$0.01
My output is $0.00.
However if I uncomment the line printf("%lf",average);
The Output is as follows
0.02 //This is the average
$0.01
I am running the code on ideone.com
Please explain why is this happening.
I believe I've found the culprit and a reasonable explanation.
On x86 processors, the FPU operates internally with extended precision, which is an 80-bit format. All of the floating point instructions operate with this precision. If a double is actually required, the compiler will generate code to convert the extended precision value down to a double precision value. Crucially, the commented-out printf forces such a conversion because the FPU registers must be saved and restored across that function call, and they will be saved as doubles (note that avg and mon are both inlined so no save/restore happens there).
In fact, instead of printf we can use the line static double dummy = average; to force the double conversion to occur, which also causes the bug to disappear: http://ideone.com/a1wadn
Your value of average is close to but not exactly 0.02 because of floating-point inaccuracies. When I do all the calculations explicitly with long double, and I print out the value of average, it is the following:
long double: 0.01999999999999999999959342418532
double: 0.02000000000000000041633363423443
Now you can see the problem. When you add the printf, average is forced to a double which pushes it above 0.02. But, without the printf, average will be a little less than 0.02 in its native extended precision format.
When you do int a=temp*100; the bug appears. Without the conversion, this makes a = 1. With the conversion, this makes a = 2.
To fix this, simply use int a=round(temp*100); - all your weird errors should vanish.
Of note, this bug is extremely sensitive to changes in the code. Anything that causes the registers to be saved (such as a printf pretty much anywhere) will actually cause the bug to vanish. Hence, this is an extremely good example of a heisenbug: a bug that vanishes when you try to investigate it.
#nneonneo well answered most of the issue: Slightly variant compilations result in slightly different floating-point code that result in nearly the same double answer, except one answer is just below 2.0 and the the other at or just about 2.0.
Like to add about the importance on not using conversion to int for floating point rounding.
Code like double temp; ... int a=temp*100; accentuate this difference resulting in a with a value of 1 or 2 as conversion to int is effective "truncate toward zero" - drop the fraction.
Rather than round to near 0.01 with code like:
double temp;
...
int a = temp*100; // Problem is here
temp = a/100.0;
Do not use int at all. Use
double temp;
...
temp = round(temp*100.0)/100.0;
Not only does this provide more consistent answers (as temp is unlikely to have values near a half-cent), it also allows temp values outside the int range. temp = 1e13; int a = temp/100; certainly results in undefined behavior.
Do not use conversion to int to round floating-point numbers: use round()
roundf(), roundl(), floor(), ceil(), etc. may also be useful. #jeff
You're dividing a double by an integer, which is integer division. In this case it will give a value of 0.
If you cast student to a double it should give you proper output.
average=average/(double)students;
There might be other locations this is needed depending on your arithmetic.

Why does this program gives no output for float and double datatypes?

Why does this program gives no output for float and double datatypes. However, what will be the result when the same code is replaced with for loop??
# include <stdio.h>
int main()
{
float x=1.1;
while (x==1.1)
{
printf("%f\n",x);
x=x-0.1;
}
return 0;
}
float x=1.1;
while (x==1.1)
float and double variables are not capable of storing the exact value of 1.1, only a very close approximation. The exact value in a float and a double will be slightly different due to the difference in precision.
1.1 is a double value. You are storing 1.1 as a double into a float which will slightly alter the value. Then you compare it with the double value 1.1 so it will not quite be equal and so will never enter your condition.
For this to work you need to write 1.1f to ensure that you are working with the same data type everywhere.
In addition I'm sure someone else will explain why comparing floating point values for exact equality is often a bad idea.

Why the same value of float and a string that is converted into float using function atof are not equal?

I have written a program in C and when I compare the same values of a float and a string that is converted into float using function atof results in NOT EQUAL .
#include<stdio.h>
main(){
char str[10] = "54.23" ;
float val = 54.23 ;
if( atof(str) == val )
printf("\nconverted correctly");
else
printf("\nThen What is the use of atof\n ");
}
This Program is showing output : "Then What is the use of atof"
Please tell me why this anonymous behavior is shown by this program ?
Never test floats/doubles for equality with ==
Here's a version of your code which actually displays the values in question:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char str[10] = "54.23";
float val = 54.23;
printf("atof(str) = %.15f\n", atof(str));
printf(" val = %.15f\n", val);
return 0;
}
When you run it you see this:
$ gcc -Wall atof.c
$ ./a.out
atof(str) = 54.229999999999997
val = 54.229999542236328
$
The values are close, within the expected accuracy of a single precision float, but they are not identical. Also, as others have noted, atof returns a double, so you are comparing the value of a float promoted to a double with a full precision double as returned by atof.
As always with this type of question, read this before proceding any further with floating point arithmetic in your code. The "take home message" is that you should never compare floats or doubles with == - always compare the absolute difference with an appropriate tolerance value.
Because val is an int; when you assign it 54.23 it'll be truncated to 54. And 54 != 54.23.
Even if it was a float, you couldn't expect them to be equal. Here's why.
double atof(char *str);\\it return double not a float
This comparison is between a float and a double.As you compare between two different types you may get some unexpected output.because every data type having different memory representation as well as different access mechanism.
float represent in memory in different form as compare to double .
you can learn more about this in wikipedia also
http://en.wikipedia.org/wiki/Floating_point#Internal_representation
Again you should include the header file
#include <stdlib.h> \\prototype of atof() present in this header.
if you not provide the proper prototype before use of the function then
return type of function by default int .So I think the return result is definitely different as you expected.
You almost never want to check equality with floating point numbers, because teensy differences will be read as unequal. There are other problems, too. For example, even if you use double precision, for instance, the decimal number "0.1" is represented as "0.10000000000000001".
In this case, your "val" variable is a double precision literal, which is cast to a float. The result probably won't be accurate perfectly. Secondly, your string literal needs to convert from base ten to a base 2 double. So, to compare the atof value to your literal, atof converts a base ten string to a base two double, while "val" was converted from a base ten literal to a base two double to a base two float, and then upcast back to a base two double to do the comparison.
Point of fact, I'm not going to pin down exactly where that lost precision went. Do as Paul's code might suggest and compare the values to within a tolerance.

Resources