C - Comparison of integer 0 vs float 0.000000 - c

I just encountered a behaviour I don't understand in a C program that I'm using.
I guess it's due to floating numbers, maybe int to float cast, but still I would like someone to explain to me that this is a normal behaviour, and why.
Here is my C program :
#include <stdio.h>
#include <float.h>
int main ()
{
printf("FLT_MIN : %f\n", FLT_MIN);
printf("FLT_MAX : %f\n", FLT_MAX);
float valueFloat = 0.000000;
int valueInt = 0;
if (valueInt < FLT_MIN) {
printf("1- integer %d < FLT_MIN %f\n", valueInt, FLT_MIN);
}
if (valueFloat < FLT_MIN) {
printf("2- float %f < FLT_MIN %f\n", valueFloat, FLT_MIN);
}
if (0 < 0.000000) {
printf("3- 0 < 0.000000\n");
} else if (0 == 0.000000) {
printf("4- 0 == 0.000000\n");
} else {
printf("5- 0 > 0.000000\n");
}
if (valueInt < valueFloat) {
printf("6- %d < %f\n", valueInt, valueFloat);
} else if (valueInt == valueFloat) {
printf("7- %d == %f\n", valueInt, valueFloat);
} else {
printf("8- %d > %f\n", valueInt, valueFloat);
}
return 0;
}
And here is my command to compile and run it :
gcc float.c -o float ; ./float
Here is the output :
FLT_MIN : 0.000000
FLT_MAX : 340282346638528859811704183484516925440.000000
1- integer 0 < FLT_MIN 0.000000
2- float 0.000000 < FLT_MIN 0.000000
4- 0 == 0.000000
7- 0 == 0.000000
A C developper that I know consider normal that the line "1-" displays become of the loss of precision in the comparison. Let's admit that.
But why the line "3-" doesn't appear then, since it's the same comparison ?
Why the line "2-" appears, since I'm comparing the same numbers ? (or at least I hope so)
And why lines "4-" and "7-" appear ? It seems a different behaviour from line "1-".
Thanks for your help.

Your confusion is probably over the line:
printf("FLT_MIN : %f\n", FLT_MIN);
change it to:
printf("FLT_MIN : %g\n", FLT_MIN);
And you will see, that FLT_MIN is actually NOT zero, but a (tiny bit) larger than zero.

FLT_MIN is not 0, it's just above 0, you just need to show more places to see that. FLT_MIN is the smallest floating point number above 0 that the computer can represent, since floating points are almost always an approximation, printf and friends round when printing, unless you ask it for the precision:
printf("FLT_MIN : %.64f\n", FLT_MIN);
3 does not actually appear in your output because 0 is not less than 0
4 is comparing 0 with 0, the computer has no problem representing both of those (0 is a special case for floats) so they compare equal
7 is the same case as 4 just with intermediate assignments

This is correct behaviour. Under IEEE754, zero is exactly representable as a float. Therefore it can be 'equal' to integer zero (although 'equivalent' would be a better term). FLT_MIN is the smallest magnitude number that can be represented as a float and still be distinguished from zero. Even though a standard %f format specifier to printf() will show FLT_MIN as 0.000000, it is not zero. A literal 0.00... will be interpreted by the compiler as float 0, which is not equal to FLT_MIN, even though the default six decimal place %f format will print them the same.

Related

Checking if a double is equal to -0.00

I am making this big program in C, which is a part of my homework. My problem is that my program is outputing x = -0.00 instead of x = 0.00. I have tried comparing like if(x==-0.00) x=fabs(x) but I've read that it won't work like that with doubles. So my question is are there any other ways to check if double is equal to negative zero?
You can use the standard macro signbit(arg) from math.h. It will return nonzero value if arg is negative and ​0​ otherwise.
From the man page:
signbit() is a generic macro which can work on all real floating-
point types. It returns a nonzero value if the value of x has its
sign bit set.
This is not the same as x < 0.0, because IEEE 754 floating point
allows zero to be signed. The comparison -0.0 < 0.0 is false, but
signbit(-0.0) will return a nonzero value.
NaNs and infinities have a sign bit.
Also, from cppreference.com:
This macro detects the sign bit of zeroes, infinities, and NaNs. Along
with copysign, this macro is one of the only two portable ways to
examine the sign of a NaN.
Very few calculations actually give you a signed negative zero. What you're probably observing is a negative value close to zero that has been truncated by your formatting choice when outputting the value.
Note that -0.0 is defined to be equal to 0.0, so a simple comparison to 0.0 is enough to verify a signed zero.
If you want to convert an exact signed zero -0.0 to 0.0 then add 0.0 to it.
Most likely, your program has a small negative value, not zero, which printf formats as “-0.00”. To print such numbers as “0.00”, you can test how printf will format them and replace the undesired string with the desired string:
#include <stdio.h>
#include <string.h>
void PrintAdjusted(double x)
{
char buffer[6];
int result = snprintf(buffer, sizeof buffer, "%.2f", x);
/* If snprintf produces a result other than "-0.00", including
a result that does not fit in the buffer, use it.
Otherwise, print "0.00".
*/
if (sizeof buffer <= result || strcmp(buffer, "-0.00") != 0)
printf("%.2f", x);
else
printf("0.00");
}
This is portable. Alternatives such as comparing the number to -0.005 have portability issues, due to implementation-dependent details in floating-point formats and rounding methods in printf.
If you truly do want to test whether a number x is −0, you can use:
#include <math.h>
…
signbit(x) && x == 0
There are two functions you need here.
First, the signbit function can tell you if the sign bit is set on a floating point number. Second, the fpclassify function will tell you if a floating point number is some form of 0.
For example:
double x = 0.0;
double y = -0.0;
double a = 3;
double b = -2;
printf("x=%f, y=%f\n", x, y);
printf("x is zero: %d\n", (fpclassify(x) == FP_ZERO));
printf("y is zero: %d\n", (fpclassify(y) == FP_ZERO));
printf("a is zero: %d\n", (fpclassify(a) == FP_ZERO));
printf("b is zero: %d\n", (fpclassify(b) == FP_ZERO));
printf("x sign: %d\n", signbit(x));
printf("y sign: %d\n", signbit(y));
printf("a sign: %d\n", signbit(a));
printf("b sign: %d\n", signbit(b));
Output:
x=0.000000, y=-0.000000
x is zero: 1
y is zero: 1
a is zero: 0
b is zero: 0
x sign: 0
y sign: 1
a sign: 0
b sign: 1
So to check if a value is negative zero, do the following:
if (fpclassify(x) == FP_ZERO)) {
if (signbit(x)) {
printf("x is negative zero\n");
} else {
printf("x is positive zero\n");
}
}
To always get the non-negative version, you don't need the comparison at all.
You can take the absolute value all of the time. If the value is non-negative, fabs should return the original value.

Why am i getting -0 instead of 0?

I have written a code in c which gives me rotation of point by angle given in the form of triples.
When I compile and run for test case it gives me output as -0,7 .
Where as the same code in python gives me output as 0,7 .
When I run the same code on online compiling platforms it gives me correct output.
I am using codeblocks windows 10 os.
Is there something wrong with codeblocks?
What should i do?
C code:
#include<stdio.h>
#include<math.h>
int main()
{
double xp,yp,xq,yq,a,b,c;
double t,xn,yn;
int z;
scanf("%d",&z);
// printf("Enter coordinates of p \n");
scanf("%lf%lf",&xp,&yp);
// printf("\nEnter triple \n");
scanf("%lf%lf%lf",&a,&b,&c);
// printf("\nEnter coordinates of q \n");
scanf("%lf%lf",&xq,&yq);
t=asin(b/c);
if(z==0)
{
xn=xp*cos(t)-yp*sin(t)-xq*cos(t)+yq*sin(t)+xq;
yn=xp*sin(t)+yp*cos(t)-xq*sin(t)-yq*cos(t)+yq;
}
else
{
xn=xp*cos(t)+yp*sin(t)-xq*cos(t)-yq*sin(t)+xq;
yn=-xp*sin(t)+yp*cos(t)+xq*sin(t)-yq*cos(t)+yq;
}
printf("%lf %lf",xn,yn);
return 0;
}
Output:
0
4 7
3 4 5
2 3
-0.000000 7.000000
Process returned 0 (0x0) execution time : 10.675 s
Press any key to continue.
https://stackoverflow.com/questions/34088742/what-is-the-purpose-of-having-both-positive-and-negative-zero-0-also-written
The most likely thing here is that you don't actually have a signed -0.0, but your formatting is presenting it to you that way.
You'll get a signed negative zero in floating point if one of your calculations yields a negative subnormal number that's rounded to zero.
If you do indeed have a pure signed zero, then one workaround is to clobber it with a the ternary conditional operator as printf does reserve the right to propagate the signed zero into the output: f == 0.0 ? 0.0 : f is one such scheme or even with the flashier but obfuscated f ? f : 0.0. The C standard defines -0.0 to be equal to 0.0. Another way (acknowledge #EricPostpischil) is to add 0.0 to the value.
For floating point values there are two zeroes 0.0 and -0.0. They compare as equal (e.g. -0.0 == 0.0 returns 1) but they are two distinct values. They are there for symmetry, because for any small value other than 0, the sign does make a mathematical difference. For some edge cases they make a difference. For example 1.0/0.0 == INFINITY and 1.0/-0.0 == -INFINITY. (INFINITY, -INFINITY and NAN) are also values that the floating point variables can take.
To make printf not print -0 for -0.0 and any small that would be truncated to 0 or -0, one way is to artificially put very small values to 0.0, for example:
if(abs(x) < 1e-5) x = 0.0;

C program not adding float correctly

I have a method that looks like this:
float * mutate(float* organism){
int i;
float sign = 1;
static float newOrg[INPUTS] = {0};
for (i = 0;i<INPUTS;i++){
if (rand() % 2 == 0) {
sign = 1;
} else {
sign = -1;
}
float temp = (organism[i] + sign);
printf("bf: %f af: %f diff: %f sign: %f sign2: %f temp: %f\n\n",
organism[i], (organism[i] + sign), (organism[i] + sign)-organism[i],
sign, sign+sign, temp);
newOrg[i] = organism[i] + sign;
}
return newOrg;
}
When sign is not 0 the first two "%f"s are the same and the 3rd is 0, also putting the sum in a variable didn't help. This is baffling me! I can post full code if needed.
Output:
bf: 117810016.000000 af: 117810016.000000 diff: 0.000000 sign: 1.000000 sign2: 2.000000 temp: 117810016.000000
Finite precision of float.
A typical float can only represent about 232 different numbers. 117,810,016.0 and 1.0 are two of them. 117,810,017.0 is not. So the C sum of 117810016.0 + 1.0 results in the "best" answer of 117810016.0.
Using a higher precision type like double often will extend the range of +1 exact math, but even that will not be exact with large enough values (typically about 9.0*10e15 or 253).
If code is to retain using float, suggest limiting organism[i] to values to the inclusive range or ±8,388,608.0 (223).
Perhaps can code simply use integer types for this task like long long.

Floating point value of 0 greater than 0

I can't reproduce this with a simple program, but somewhere in my program I have something like:
float e = f(...);
if (e > 0.0f) {
...
printf("%f", e) shows that e is 0.000000, yet e > 0.0f is true... So is e > 0 and e > 0.0. What am I missing?
The floating point value is larger than zero, but less than 1e-7. It's printing issue. Use scientific notation printf("%e", value); or "%g" for shortest notation.
The problem is that the floating point value is greater than 0, but less than the precision that printf uses to print floating point numbers with %f. You can use %e or %g for better results as illustrated with the following program.
#include <math.h>
#include <stdio.h>
void main(void)
{
int i;
float e;
for (i = 1; i < 64; i++) {
printf("Decimal places: %d\n", i);
e = 1.0 / pow(10, i);
if (e > 0.0f) {
printf("Value displayed with %%e: %e > 0.0f\n", e);
printf("Value displayed with %%f: %f > 0.0f\n", e);
printf("Value displayed with %%g: %g > 0.0f\n\n", e);
}
}
}
You will need to compile this with the maths library. For gcc use: -lm
The fact that printf("%f", e) shows it to be zero doesn't mean anything, because printf rounds the value both to decimal floating point and to the precision of the output, so very small numbers larger than 0 are likely to be put out as 0.
Try printf("%e", e) or printf("%.17f", e) and see what happens.
Your problem is that e is actually not zero. It has some tiny value in it, but that gets hidden because %f converts to decimal, losing precision. Use printf("%e",e) instead as your debug statement, and you will see that there is a nonzero value in there.

Why does this integer division yield 0?

Could someone tell me why the following code is outputting 0 at the marked line?
It seems as if everything is correct but then when I try to get the result near the end it's giving me 0 each time.
#include <stdio.h>
int main() {
// Gather time-lapse variables
int frameRate, totalLengthSecs;
printf("How many frames per second: ");
scanf("%i", &frameRate);
printf("--> %i frames confirmed.", frameRate);
printf("\nDesired length of time-lapse [secs]: ");
scanf("%i", &totalLengthSecs);
printf("--> %i seconds confirmed.", totalLengthSecs);
int totalFrames = frameRate * totalLengthSecs;
printf("\nYou need %i frames.", totalFrames);
// Time-lapse interval calculation
int timeLapseInterval = totalLengthSecs / totalFrames;
printf("\n\n%i", timeLapseInterval); // <-- this prints 0
return 0;
}
In short: Integer division truncates
You need the following:
double timeLapseInterval = (double) totalLengthSecs / (double)totalFrames;
printf("\ntimeLapseInterval : %f \n", timeLapseInterval);
You are performing integer math.
Math between two integers will produce an integer. And the result will be rounded towards zero.
This line:
totalLengthSecs / totalFrames;
Is likely producing a result that's between 0 and 1. And getting rounded to 0
You are printing integers and therefore it will round down the value.
timeLapseInterval / totalFrames will be (1 / frameRate) which will be < 1 unless frameRate is 1 (or 0 in which case you have an error dividing by 0)
When you divide 2 numbers in C and the denominator is integer, the compiler intends it as an integer division. Therefore, if you divide 1 divided 2, it returns zero and not 0.5
Moreover, your output variable is an integer too, hence, if you expect decimal outputs, you won't get it.
You can fix it by doing:
float timeLapseInterval = totalLengthSecs / (float)totalFrames;
printf("\n\n%f", timeLapseInterval);
I hope this helps

Resources