Integer conversion to double in C yielding zero values - c

I originally had a function that uses pow(), and I noticed it was returning zero values every time. While debugging it, I found that this seems to be the source of the problem:
#include <math.h>
#include <stdio.h>
#include <string.h>
int foo(int n)
{
printf("%d is number passed in \n", n);
double base = (double) n;
printf("%d is base \n", base);
printf("%d is power\n", pow(base ,2));
return (1/2 *( pow( (double) n, 2)));
}
If I call foo on any integer value (say, 8), the second printf statement prints zero every time. (And of course, the third one does as well). Shouldn't conversion of double to int be straightforward?

You got several things wrong.
First of all, you're using the %d specifier in printf, but you're passing to it a double value; for doubles, you should use %f1, otherwise the printf will try to interpret the bytes of the double as an int, leading to unexpected results (in your case 0).
Notice that this kind of error is usually noticed by recent compilers with warning level high enough.
Moreover, in the return statement you wrote
1/2 *( pow( (double) n, 2))
This expression will always yield zero, because of the 1/2 factor. Both 1 and 2 are ints, thus an integer division is performed, and obviously it results in 0, that kills the whole expression.
Solution: change the 1/2 to 1/2. (where 2. denotes 2 as a double value, which promotes the operation to a floating-point division), or simply replace it with 0.5, or (even simpler) perform a division by two at the end of the expression.
Trivia: I always had the doubt that %f was for float, and something else was used for doubles; instead, it turns out that there's no specifier for floats, since they are automatically converted to doubles when passed to a function as "variable arguments" (so this applies to printf).

printf("%g is base \n", base);
printf("%g is power\n", pow(base ,2));
Your second problem is that you're doing this:
return (1/2 *( pow( (double) n, 2)));
But have defined your function to return an int. You need to define it to return double and not use integer math there :)

Your version
with correct conversion specifications
with no casts
with 1.0 in the final return

to output a double in c via printf, you should use %g or %lf (lf stands for "long float" which is a double, in fact float stands for single precision :D )
%g truncate to the least significant number, %lf do not.
You can even use something like
%.20g, so you are asking to write the number with 20 decimal number after dot (or comma).
If you want to get a float result from your function, you shoud change the function declaration to
double foo(int n)
I suggest to change the return line to this
return (0.5 * pow( (double) n, 2)));
0.5 is the right way to write 1/2 in floating point.
But if you only want an integer, then you should do this:
return ((int)pow( (double) n, 2)/2);
In fact pow return a double, and you should cast it to integer
Hope that's usefull :)

Related

The problem about printf function to "output float with %d" in C

I am a newbie to the C language. When I was learning floating point numbers today, I found the following problems.
float TEST= 3.0f;
printf("%x\n",TEST);
printf("%d\n",TEST);
first output:
9c9e82a0
-1667333472
second output:
61ea32a0
1642738336
As shown above, each execution will output different results. I have checked a lot of IEEE 754 format and still don't understand the reasons. I would like to ask if anyone can explain or provide keywords for me to study, thank you.
-----------------------------------Edit-----------------------------------
Thank you for your replies. I know how to print IEEE 754 bit pattern. However, as Nate Eldredge, chux-Reinstate Monica said, using %x and %d in printf is undefined behavior. If there is no floating point register in our device, how does it work ? Is this described in the C99 specification?
Most of the time, when you call a function with the "wrong kind" (wrong type) of argument, an automatic conversion happens. For example, if you write
#include <stdio.h>
#include <math.h>
printf("%f\n", sqrt(144));
this works just fine. The compiler knows (from the function prototype in <math.h>) that the sqrt function expects an argument of type double. You passed it the int value 144, so the compiler automatically converted that int to double before passing it to sqrt.
But this is not true for the printf function. printf accepts arguments of many different types, and as long as each argument is right for the particular % format specifier it goes with in the format string, it's fine. So if you write
double f = 3.14;
printf("%f\n", f);
it works. But if you write
printf("%d\n", f); /* WRONG */
it doesn't work. %d expects an int, but you passed a double. In this case (because printf is special), there's no good way for the compiler to insert an automatic conversion. So, instead, it just fails to work.
And when it "fails", it really fails. You don't even necessarily get anything "reasonable", like an integer representing the bit pattern of the IEEE-754 floating-point number you thought you passed. If you want to inspect the bit pattern of a float or double, you'll have to do that another way.
If what you really wanted to do was to see the bits and bytes making up a float, here's a completely different way:
float test = 3.14;
unsigned char *p = (unsigned char *)&test;
int i;
printf("bytes in %f:", test);
for(i = 0; i < sizeof(test); i++) printf(" %02x", p[i]);
printf("\n");
There are some issues here with byte ordering ("endianness"), but this should get you started.
To print hex (ie how it is represented in the memory) representation of the float:
float TEST= 3.0f;
int y=0;
memcpy(&y, &TEST, sizeof(y));
printf("%x\n",y);
printf("%d\n",y);
or
union
{
float TEST;
int y;
}uf = {.y = 0};
uf.TEST = 3.0f;
printf("\n%x\n",(unsigned)uf.y);
printf("%d\n",uf.y);
Both examples assuming sizeof(float) <= sizeof(int) (if they are not equal I need to zero the integer)
And the result (same for both):
40400000
1077936128
As you can see it is completely different from your one.
https://godbolt.org/z/Kr61x6Kv3

floating point exception(core dumped)

I tried with putting puts("..") to find where the mistake is, but it didn't help.
this is my third function, first and second are working.
i translated in englih, i hope it's understandably.
void write3(sth_st*E, int n, char* Typ){
int i;
int sum=0;
int count=0;
float result;
for(i=0; i<n; i++){
if(strcmp(Typ, E[i].typ)==0){
sum=sum+E[i].time;
count++;
}
}
FILE*write3;
write3=open("xD", "w");
puts("rand");
result=sum/count;
fprintf(write3, "%f", result);
return;
}
count is most likely integer and 0. The system error message is misleading, especially since dividing by 0 is perfectly valid for floating point values.
With the extra context, we can infer that Typ was not found in the E array or maybe n is too small, so count and sum both stay at 0 and the division sum/count invokes undefined behavior because it is an integer division.
If you convert one or the other to double, you will get a floating point division, which is undoubtedly what you expect and printf will print nan for this case.
result = (double)sum / count;
There is also a possiblity that the sum of all times may overflow the int type. You should make sum a double to avoid that.
Note that %f is the printf format for double. result is a float, but luckily floats are silently converted to double when passed to printf. There is no benefit at using float types, use double instead.

Trying to print answer to equation and getting zero in C.

printf("Percent decrease: ");
printf("%.2f", (float)((orgChar-codeChar)/orgChar));
I'm using this statement to print some results to my command console, however, I end up with zero. Putting the equation into another variable doesn't work either.
orgChar = 91 and codeChar = 13, how do I print out this equation?
Integer division will lead to result 0 here and you are type casting the result later to float so eventually you will end up with 0
Make any one of the variables float before division
(orgChar-codeChar)/(float)orgChar
As others have mentioned, the subtraction and division are done using integer math before the cast to (float). By that point, the integer division has a truncated result of 0. Instead:
// (float)((orgChar-codeChar)/orgChar)
((float) orgChar - codeChar)/orgChar
// or
(orgChar - codeChar)/ (float) orgChar
As the float argument gets converted to double as part of the "usual argument promotion" of arguments to a variadic function like printf(), might as well do
printf("%.2f", (orgChar-codeChar)/ (double) orgChar);
Casting, in general, should be avoided. Some casts unintentionally narrow the operation. If unsigned is 32-bit and a1 is uint64_t, then a1 was narrowed before the shift and unexpected results may occur. If a1 was a char, it is nicely converted without trouble to an unsigned.
The second method of *1u will not narrow. It will insure a2*1u is at least the width of an unsigned.
unsigned sh1 = (unsigned) a1 >> b1; // avoid
unsigned sh2 = a2*1u >> b2; // better
So recommend, rather than (float) or (double), use the idiom of multiplying by 1.
printf("%.2f", (orgChar - codeChar) * 1.0 / orgChar);
you don't need to typecast the whole expression. you can simply type cast either the numerator or the denominator to get the float result with precision of 2 decimal places.
for eg:
here in this code defining a variable c as float doesnt guarantee the result to be float.for getting the precise result you need to typecast either the numerator or denominator.
You shouldn't need to cast to float at all. Simply make sure both variables are of type float or double before attempting to print them as floats. This means either declaring the variables as floats, or using the correct function, such as atof () when converting the data to floats (normally this is done when you get the data from the command-line or a file.)
This should work...
#include <stdio.h>
int
main (void)
{
float orgChar = 91;
float codeChar = 13;
printf ("%.2f\n", (orgChar - codeChar) / orgChar);
return 0;
}

Why does 1/2 in c = -2010232232?

I have a very simple C program.
int main(void){
double sum = 1/2;
printf("%d\n", sum);
return 0;
}
Why does it return a number like "-2030243223"?
And why does this number change every time I run the program?
I've tried using int's and float's but I can't seem to get the output to be 0.5!?
Use %f to print a double, not %d. The latter causes undefined behavior.
Also the expression 1/2 uses integer division which yields 0, so to get .5, use 1/2. (note trailing period).
Finally, to actually get .5 instead of something like 0.500000, specify the precision:
printf("%.1f\n", sum);
You're passing an IEEE floating-point number to printf, but telling it it's an integer.
Change
printf("%d\n", sum);
to
printf("%f\n", sum);
As noted in other comments, you probably also want to do floating-point division rather than integer division. 1/2 is zero; you're dividing two integers, so the result is an integer (yes, even though you're about to assign it into a floating-point variable -- each expression's type is determined in isolation) and it has to discard the remainder. You probably want 1.0/2 instead; if either term is a float, then the result is a float, so you'll get 0.5.
You're trying to print a double to an Integer. (%d).
Even though they both are numbers, internally there are huge differences, for example, memory ones.
You're trying to print a double as an int. Try using:
printf("%g\n");
Also, you will want to make you initial division 1.0/2.0 or else you will get 0.
Try this:
int main(void){
double sum = 1.0/2.0;
printf("%10.3f\n", sum);
return 0;
}
There is a couple of issues with your code
int main(void){
// you need to divide a double by a double, not two ints
double sum = 1.0/2.0;
// %d is for int, not doubles. You use %f in the case of printing a double
printf("%f\n", sum);
return 0;
}
Now if you really want to print the variable as an int, you can cast the variable sum as an int by doing printf("%d\n", (int)sum);, but you'll have a rounding issue.
Try the following:
printf("%f\n", sum);
%d is a placeholder for integer, maybe the address of sum has been printed out^^
The bad format can't be the whole answer, because:
With OP's code, the double should be zero, stored as 0x0000000000000000, which couldn't show as "-2030243223" (0x86FCF269).
OP says this value changes all the time.
So there must be something else, such as the fact that the header is missing: I guess the compiler doesn't know printf is a variadic function, and tries to pass the argument through floating-point registers.
printf, being a variadic function, probably attempts to read its input value from the stack, hence garbage.

Floating point rounding in C

I've run into some weird rounding behaviour with floats. The code below demonstrates the problem. What is the best way to solve this? I've been looking for solutions but haven't had much luck.
#include<stdio.h>
int main(void)
{
float t;
t = 5592411;
printf("%f\n", 1.5*t);
t *= 1.5;
printf("%f\n", t);
return 0;
}
The code above should print out the same value, but I get this on my setup using GCC 4.7.2:
8388616.500000
8388616.000000
If I use a calculator, I get the first value, so I assume the second is being rounded somehow. I have identical Fortran code which does not round the value(has the 0.5).
1.5 is a double constant rather than a float and C has automatic promotion rules. So when you perform 1.5*t what happens is (i) t is converted to a double; (ii) that double is multiplied by the double 1.5; and (iii) the double is printed (as %f is the formatter for a double).
Conversely, t *= 1.5 promotes t to a double, performs a double multiplication and then truncates the result to store it back into a [single precision] float.
For evidence, try either:
float t;
t = 5592411;
printf("%f\n", 1.5f*t); // multiply a float by a float, for no promotion
t *= 1.5;
printf("%f\n", t);
return 0;
Or:
double t; // store our intermediate results in a double
t = 5592411;
printf("%f\n", 1.5f*t);
t *= 1.5;
printf("%f\n", t);
return 0;
The first calculation is done with double precision, the second is calculated the same, but truncated to single precision in the assignment to float.
If you use double for your variable, you'll get the same result. It's a good idea to use this type over float whenever accuracy may be a concern.
In the first case, the result is a double which can precisely represent the desired value.
In the second case, the result is a float which can't precisely represent the desired value.
Try the same with double and you'll end up with the same results either way.
#include<stdio.h>
int main(void)
{
double t;
t = 5592411;
printf("%f\n", 1.5*t);
t *= 1.5;
printf("%f\n", t);
return 0;
}
Writing 1.5 in C code is interpreted as a double, which has more precision than the float type.
The first case,
printf("%f\n", 1.5*t);
results in t being implicitly converted to a double (with greater precision) and then multiplied. The printf function, which casts the input corresponding to %f anyway, prints the result, which is also a double.
The second case has the 1.5 being converted to the float type, which has less precision and cannot store as small details.
If you want to avoid this effect, use 1.5f instead on 1.5 to use floats, or change the type of t to double.
Whether this would work at all depends on the machine representation of floats and doubles. Passing a float on a typical 32 bit architecture pushes 4 bytes on the argument stack. Passing a double would push 8 bytes. Passing a double but using %f is asking to treat it as a float which will look at the first 4 bytes pushed in our typical case. Depending on machine representation this might be close to the intended result or might be way out in left field.

Resources