Can I not provide an equality condition in a while loop? - c

I wrote this code and only 'Hello' got printed.
float x=1.1;
printf("Hello\n");
while(x-1.1==0)
{
printf("%f\n",x);
x=x-1;
}

When you are dealing with floating point operations, you don't get the results as you would expect.
What you are seeing is:
1.1 is represented as a float in x.
In the while statement, 1.1 is of type double, not float. Hence, x is promoted to a double before the subtraction and comparison is made.
You lose precision in these steps. Hence x-1.1 does not evaluate to 0.0.
You can see expected results if you use appropriate floating point constants.
#include <stdio.h>
void test1()
{
printf("In test1...\n");
float x=1.1;
// Use a literal of type float, not double.
if (x-1.1f == 0)
{
printf("true\n");
}
else
{
printf("false\n");
}
}
void test2()
{
printf("In test1...\n");
// Use a variable of type double, not float.
double x=1.1;
if (x-1.1 == 0)
{
printf("true\n");
}
else
{
printf("false\n");
}
}
int main()
{
test1();
test2();
return 0;
}
Output:
In test1...
true
In test2...
true

This is because x is a single-precision floating-point number, but you subtract the constant 1.1 from it, which is double-precision. So your single-precision 1.1 is converted to double-precision, and the subtraction is performed, but the result is non-zero (since 1.1 cannot be exactly represented, but the double-precision value is closer than the single-precision value). Try the following:
#include <stdio.h>
int main()
{
float x = 1.1;
double y = 1.1;
printf("%.20g\n", x - 1.1);
printf("%.20g\n", y - 1.1);
return 0;
}
On my computer, the result is:
2.384185782133840803e-08
0

Compare float like -0.000001 < x - 1.1 && x - 1.1 < 0.00001

You need to read up on floating point precision.
TL;DR is - x-1.1 is not really round 0.
for example, in my debugger, x equals to 1.10000002 - this is due to the nature of the floating point precision.
Relevant read:
http://floating-point-gui.de/

Related

Alternative to ceil() and floor() to get the closest integer values, above and below of a floating point value?

I´m looking for an alternative for the ceil() and floor() functions in C, due to I am not allowed to use these in a project.
What I have build so far is a tricky back and forth way by the use of the cast operator and with that the conversion from a floating-point value (in my case a double) into an int and later as I need the closest integers, above and below the given floating-point value, to be also double values, back to double:
#include <stdio.h>
int main(void) {
double original = 124.576;
double floorint;
double ceilint;
int f;
int c;
f = (int)original; //Truncation to closest floor integer value
c = f + 1;
floorint = (double)f;
ceilint = (double)c;
printf("Original Value: %lf, Floor Int: %lf , Ceil Int: %lf", original, floorint, ceilint);
}
Output:
Original Value: 124.576000, Floor Int: 124.000000 , Ceil Int: 125.000000
For this example normally I would not need the ceil and floor integer values of c and f to be converted back to double but I need them in double in my real program. Consider that as a requirement for the task.
Although the output is giving the desired values and seems right so far, I´m still in concern if this method is really that right and appropriate or, to say it more clearly, if this method does bring any bad behavior or issue into the program or gives me a performance-loss in comparison to other alternatives, if there are any other possible alternatives.
Do you know a better alternative? And if so, why this one should be better?
Thank you very much.
Do you know a better alternative? And if so, why this one should be better?
OP'code fails:
original is already a whole number.
original is a negative like -1.5. Truncation is not floor there.
original is just outside int range.
original is not-a-number.
Alternative construction
double my_ceil(double x)
Using the cast to some integer type trick is a problem when x is outsize the integer range. So check first if x is inside range of a wide enough integer (one whose precision exceeds double). x values outside that are already whole numbers. Recommend to go for the widest integer (u)intmax_t.
Remember that a cast to an integer is a round toward 0 and not a floor. Different handling needed if x is negative/positive when code is ceil() or floor(). OP's code missed this.
I'd avoid if (x >= INTMAX_MAX) { as that involves (double) INTMAX_MAX whose rounding and then precise value is "chosen in an implementation-defined manner". Instead, I'd compare against INTMAX_MAX_P1. some_integer_MAX is a Mersenne Number and with 2's complement, ...MIN is a negated "power of 2".
#include <inttypes.h>
#define INTMAX_MAX_P1 ((INTMAX_MAX/2 + 1)*2.0)
double my_ceil(double x) {
if (x >= INTMAX_MAX_P1) {
return x;
}
if (x < INTMAX_MIN) {
return x;
}
intmax_t i = (intmax_t) x; // this rounds towards 0
if (i < 0 || x == i) return i; // negative x is already rounded up.
return i + 1.0;
}
As x may be a not-a-number, it is more useful to reverse the compare as relational compare of a NaN is false.
double my_ceil(double x) {
if (x >= INTMAX_MIN && x < INTMAX_MAX_P1) {
intmax_t i = (intmax_t) x; // this rounds towards 0
if (i < 0 || x == i) return i; // negative x is already rounded up.
return i + 1.0;
}
return x;
}
double my_floor(double x) {
if (x >= INTMAX_MIN && x < INTMAX_MAX_P1) {
intmax_t i = (intmax_t) x; // this rounds towards 0
if (i > 0 || x == i) return i; // positive x is already rounded down.
return i - 1.0;
}
return x;
}
You're missing an important step: you need to check if the number is already integral, so for ceil assuming non-negative numbers (generalisation is trivial), use something like
double ceil(double f){
if (f >= LLONG_MAX){
// f will be integral unless you have a really funky platform
return f;
} else {
long long i = f;
return 0.0 + i + (f != i); // to obviate potential long long overflow
}
}
Another missing piece in the puzzle, which is covered off by my enclosing if, is to check if f is within the bounds of a long long. On common platforms if f was outside the bounds of a long long then it would be integral anyway.
Note that floor is trivial due to the fact that truncation to long long is always towards zero.

This program prints "hello" instead of "Hi". How? [duplicate]

This question already has answers here:
strange output in comparison of float with float literal
(8 answers)
Closed 4 years ago.
Below is the program for if and else
#include<stdio.h>
#include<conio.h>
int main()
{
float a = 0.7; //a declared as float variable
if(a == 0.7) //why it takes only integral part of 0.7
{
printf("Hi");
}
else
{
printf("hello");
}
return 0;
}
Shouldn't this program display Hi instead of hello as 0.7 is equal to 0.7?
(I'm new to C programming)
Note that
float a = 0.7;
converts a double value 0.7 to a float and then
if(a == 0.7)
converts a to a double.
Since 0.7 cannot be exactly represented in floating point, the float and double representations are not quite the same.
You can force the compiler to stay with float like this
#include<stdio.h>
int main()
{
float a = 0.7f;
if(a == 0.7f)
{
printf("Hi");
}
else
{
printf("hello");
}
return 0;
}
And now the program prints "Hi" because it is comparing like with like.
More generally you must be very wary of floating point comparisons for equality
#include<stdio.h>
int main()
{
double d = 2.1;
d /= 3.0;
if(d == 0.7) {
puts("Equal");
}
else {
puts("Unequal");
}
printf("%.17f\n", d);
printf("%.17f\n", 0.7);
return 0;
}
Program output
Unequal
0.70000000000000007
0.69999999999999996
If you change datatype of a to double, it'll print hi,
This is because constants in floating point stored in double and non floating in long,
double precision is high and float has less precise, double value stored in 64 bit binary and float value stored in 32 bit binary, it'll be completely clear if you see the method of floating point numbers conversion to binary convertion.

How to compare double variables in the if statement

As I am trying to compare these doubles, it won't seem to be working correctly
Here it goes: (This is exactly my problem)
#include <stdio.h>
#include <math.h>
int main () {
int i_wagen;
double dd[20];
dd[0]=0.;
dd[1]=0.;
double abstand= 15.;
double K_spiel=0.015;
double s_rel_0= K_spiel;
int i;
for(i=1; i<=9; i++)
{
i_wagen=2*(i-1)+2;
dd[i_wagen]=dd[i_wagen-1]-abstand;
i_wagen=2*(i-1)+3;
dd[i_wagen]=dd[i_wagen-1]-s_rel_0;
}
double s_rel=dd[3-1]-dd[3];
if((fabs(s_rel) - K_spiel) == 0.)
{
printf("yes\n");
}
return(0);
}
After executing the programm, it wont print the yes.
How to compare double variables in the if statement?
Take under account limited precision of the double representation of floating point numbers!
Your problem is simple and covered in Is floating point math broken?
Floating point operations are not precise. The representation of the given number may not be precise.
For 0.1 in the standard binary64 format, the representation can be written exactly as 0.1000000000000000055511151231257827021181583404541015625
Double precision (double) gives you only 52 bits of significant, 11 bits of exponent, and 1 sign bit. Floating point numbers in C use IEEE 754 encoding.
See the output of your program and the possible fix where you settle down for the variable being close to 0.0:
#include <stdio.h>
#include <math.h>
#define PRECISION 1e-6
int main (void) {
int i_wagen;
double dd[20];
dd[0]=0.;
dd[1]=0.;
double abstand= 15.;
double K_spiel=0.015;
double s_rel_0= K_spiel;
int i;
for(i=1; i<=9; i++)
{
i_wagen = 2*(i-1)+2;
dd[i_wagen] = dd[i_wagen-1]-abstand;
i_wagen = 2*(i-1)+3;
dd[i_wagen] = dd[i_wagen-1] - s_rel_0;
}
double s_rel = dd[3-1]-dd[3];
printf(" s_rel %.16f K_spiel %.16f diff %.16f \n" , s_rel, K_spiel, ((fabs(s_rel) - K_spiel)) );
if((fabs(s_rel) - K_spiel) == 0.0) // THIS WILL NOT WORK!
{
printf("yes\n");
}
// Settle down for being close enough to 0.0
if( fabs( (fabs(s_rel) - K_spiel)) < PRECISION)
{
printf("yes!!!\n");
}
return(0);
}
Output:
s_rel 0.0150000000000006 K_spiel 0.0150000000000000 diff 0.0000000000000006
yes!!!
You're comparing x to two different matrix entries: the first if compares x to coeff[0][0], the second to coeff[0][1]. So if x is greater than coeff[0][0] and less than or equal to coeff[0][1] the program will execture the final else branch. You probably want to compare x to the same matrix entry in both if statements. And in that case, the last else branch would be useless, since one of the three cases (less than, equal to or greater than) MUST be true.
First, dd[i_wagen-1] as used in the statement:
dd[i_wagen]=dd[i_wagen-1]-abstand;
is uninitialized. Code will run, but will have unpredictable results.
To initialize, you can use:
double dd[20]={0}; //sufficient
or possibly
double dd[20]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; //explicit, but not necessary
Moving to your actual question, it all comes down to this statement:
if((fabs(s_rel) - K_spiel) == 0.)
You have initialized K_spiel to 0.015. And at this point in your execution flow s_rel appears to be close to 0.015. But it is actually closer to 0.0150000000000006. So the comparison fails.
One trick that is commonly used is to define an epsilon value, and use it to determine if the difference between two floating point values is small enough to satisfy your purpose:
From The Art of Computer Programming, the following snippet uses this approach, and will work for your very specific example: (caution: Read why this approach will not work for all floating point related comparisons.)
bool approximatelyEqual(float a, float b, float epsilon)
{
return fabs(a - b) <= ( (fabs(a) < fabs(b) ? fabs(b) : fabs(a)) * epsilon);
}
So replace the line:
if((fabs(s_rel) - K_spiel) == 0.)
with
if(approximatelyEqual(s_rel, K_spiel, 1e-8)

why if(a==2.3) evaluates false when float a=2.3 [duplicate]

This question already has answers here:
Why are floating point numbers inaccurate?
(5 answers)
Closed 6 years ago.
#include<stdio.h>
void main()
{
float a = 2.3;
if(a == 2.3) {
pritnf("hello");
}
else {
printf("hi");
}
}
It prints "hi" in output, or we can say that if condition is getting false value.
#include<stdio.h>
void main()
{
float a = 2.5;
if(a == 2.5)
printf("Hello");
else
printf("Hi");
}
It prints hello.
The variable a is a float that holds some value close to the mathematical value 2.3.
The literal 2.3 is a double that also holds some value close to the mathematical value 2.3, but because double has greater precision than float, this may be a different value from the value of a. Both float and double can only represent a finite number of values, so there are necessarily mathematical real numbers that cannot be represented exactly by either of those two types.
In the comparison a == 2.3, the left operand is promoted from float to double. This promotion is exact and preserves the value (as all promotions do), but as discussed above, that value may be a different one from that of the 2.3 literal.
To make a comparison between floats, you can use an appropriate float literal:
assert(a == 2.3f);
// ^
2.3 with binary representation is 01000000000100110011001100110011...
so you are not able to set a float exactly to 2.3
with double precision you get something similar: 2.299999952316284
you converted a double to float when you wrote:
float a = 2.3;
the if checks if the float a is equal to double 2.299999952316284
you should write:
float a = 2.3f;
and you can check:
if (a == 2.3f) {
...
}
i would rather test with:
if (fabs(a - 2.3f) < 0.00001) {
...
}
the 2.5 represented with bits is: 01000000001000000000000000000000
EDIT: fabs is part of the <math.h> or <cmath>
Read this: article
Comparing floating point values is not as easy as it might seem, have a look at Most effective way for float and double comparison.
It all boils down to the fact, that floating point numbers are not exact (well
most are not). Usually you compare 2 floats by allowing a small error window (epsilon):
if( fabs(a - 2.3f) < epsion) { ... }
where epsilon is small enough for your calculation, but not too small (bigger than Machine epsilon).

Comparing float and double

#include <stdio.h>
int main(void){
float a = 1.1;
double b = 1.1;
if(a == b){
printf("if block");
}
else{
printf("else block");
}
return 0;
}
Prints: else block
#include <stdio.h>
int main(void){
float a = 1.5;
double b = 1.5;
if(a == b){
printf("if block");
}
else{
printf("else block");
}
return 0;
}
Prints: if block
What is the logic behind this?
Compiler used: gcc-4.3.4
This is because 1.1 is not exactly representable in binary floating-point. But 1.5 is.
As a result, the float and double representations will hold slightly different values of 1.1.
Here is exactly the difference when written out as binary floating-point:
(float) 1.1 = (0.00011001100110011001101)₂
(double)1.1 = (0.0001100110011001100110011001100110011001100110011010)₂
Thus, when you compare them (and the float version gets promoted), they will not be equal.
Must read: What Every Computer Scientist Should Know About Floating-Point Arithmetic
The exact value of 1.1 decimal in binary is non-ending fraction 1.00011001100110011001100(1100).... The double constant 1.1 is 53-bit truncation / approximate value of that mantissa. Now this when converted to float, the mantissa will be represented just in 24 bits.
When the float is converted back to double, the mantissa is now back to 53 bits, but all memory of the digits beyond 24 are lost - the value is zero-extended, and now you're comparing (for example, depending on the rounding behaviour)
1.0001100110011001100110011001100110011001100110011001
and
1.0001100110011001100110000000000000000000000000000000
Now, if you used 1.5 instead of 1.1;
1.5 decimal is exactly 1.1 in binary. It can be presented exactly in just 2 bit mantissa, therefore even the 24 bits of float are an exaggeration... what you have is
1.1000000000000000000000000000000000000000000000000000
and
1.10000000000000000000000
The latter, zero extended to a double would be
1.1000000000000000000000000000000000000000000000000000
which clearly is the same number.

Resources