Convert int to double - c

I ran this simple program, but when I convert from int to double, the result is zero. The sqrt of the zeros then displays negative values. This is an example from an online tutorial so I'm not sure why this is happening. I tried in Windows and Unix.
/* Hello World program */
#include<stdio.h>
#include<math.h>
main()
{ int i;
printf("\t Number \t\t Square Root of Number\n\n");
for (i=0; i<=360; ++i)
printf("\t %d \t\t\t %d \n",i, sqrt((double) i));
}

Maybe this?
int number;
double dblNumber = (double)number;

The problem is incorrect use of printf format - use %g/%f instead of %d
BTW - if you are wondering what your code did here is some abridged explanation that may help you in understanding:
printf routine has treated your floating point result of sqrt as integer. Signed, unsigned integers have their underlying bit representations (put simply - it's the way how they are 'encoded' in memory, registers etc). By specifying format to printf you tell it how it should decipher that bit pattern in specific memory area/register (depends on calling conventions etc). For example:
unsigned int myInt = 0xFFFFFFFF;
printf( "as signed=[%i] as unsigned=[%u]\n", myInt, myInt );
gives: "as signed=[-1] as unsigned=[4294967295]"
One bit pattern used but treated as signed first and unsigned later. Same applies to your code. You've told printf to treat bit pattern that was used to 'encode' floating point result of sqrt as integer. See this:
float myFloat = 8.0;
printf( "%08X\n", *((unsigned int*)&myFloat) );
prints: "41000000"
According to single precision floating point encoding format.
8.0 is simply (-1)^0*(1+fraction=0)*2^(exp=130-127)=2*3=8.0 but printed as int looks like just 41000000 (hex of course).

sqrt() return a value of type double. You cannot print such a value with the conversion specifier "%d".
Try one of these two alternatives
printf("\t %d \t\t\t %f \n",i, sqrt(i)); /* use "%f" */
printf("\t %d \t\t\t %d \n",i, (int)sqrt(i)); /* cast to int */
The i argument to sqrt() is converted to double implicitly, as long as there is a prototype in scope. Since you included the proper header, there is no need for an explicit conversion.

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

Printing an integer with a float conversion code (%f)?

So I've been looking into c programming and bought a book. There's a problem at the end of a chapter that reads:
write a program that defines five integer variables and initializes them to 1, 10, 100, 1000, 10000. It then prints them on a single line separated by space characters using the decimal conversion code (%d), and on the nest line with the float conversion code (%f). Note the differences between the results. How do you explain to them?
Now, my question is how do you use the float conversion code for a number that is defined as an int?
This is what I have written so far:
#include <stdio.h>
int main(void)
{
int one = 1;
int ten = 10;
int hundred = 100;
int thousand = 1000;
int tenThous = 100000;
printf("%d %d %d %d %d \n", one, ten, hundred, thousand, tenThous);
printf("%f %f %f %f %f \n", one, ten, hundred, thousand, tenThous);
return 0;
}
In the way they describe the problem, I think I have to use the int variables that I had defined. It would be easy to make a new set of numbers and declare them as floats, but I don't think this is exactly what they're asking.
The error message that I get when compiling is:
numPrint.c:12:33: warning: format specifies type 'double' but the argument has
type 'int' [-Wformat]
printf("%f %f %f %f %f \n", one, ten, hundred, thousand, tenThous);
~~ ^~~
%d
and it goes through all the int variables, saying that the format specifies for a 'double' and the variable used is 'int'
Is there a way to do this?
Is there a way to do this?
You have done it. The messages are warnings; they will not have aborted compilation.
Or maybe you're asking whether you can do it without eliciting warnings? Sure you can. The message tells you what warning flag that particular diagnostic is associated with: -Wformat. You can disable those warnings by passing -Wno-format as a command-line option.
But you shouldn't.
The warnings are telling you about a bona fide problem in your code. Just as it explains, the %f descriptor expects the corresponding argument to have type double. Alternatively, float will work, too, since it is automatically converted to double in this particular context, but if the argument has a different type then the behavior is undefined. You could cast the arguments to type double, but that's not what I interpret the text to be asking you to do.
What should you do instead? Burn the book and get a better one. Really. There is no justification for a textbook on C to suggest doing what yours seems to have suggested. Even if it's just poorly worded, you have to wonder what other stinkers are waiting for you there. Burning the book instead of returning it or giving it away constitutes a community service.
You can cast the printf() arguments to floats like this:
printf("%f %f %f %f %f \n", (float)one, (float)ten, (float)hundred, (float)thousand, (float)tenThous);

how to keep decimals in c

I am writing simple code for homework.
I get one number from user, which is 3.4, when I define it with
scanf("%d",&a)
it takes only 3 and do it that way. I defined a as
int a;
What should I do?
I think you are very new to c programming. This is a very simple job. This can be done as:-
float a;
// to input a data in the variable a
scanf("%f",&a);
//to display the stored data
printf("%f\n",a);
//or
printf("%.nf\n",a);//specify value of n
//maximum value of n is 6 also is its default value
//for e.g. printf("%.2f",a); will display decimal number upto two digits after the decimal place
//you can know more about displaying data as
%d: decimal value (int)
%c: character (char)
%s: string (const char *)
%u: unsigned decimal value (unsigned int)
%ld: long int (long)
%f: float value (float or double)
%x: decimal value in Hexadecimal format
%o: decimal value in octal format
For avialabe list of formatting specifications go here
Use float
float a;
scanf("%f", &a);
%d is for int. 3.4 is not an int type, you can use float.
float x;
scanf("%f", &x);
For detailed information about data types, you can check here: http://en.wikipedia.org/wiki/C_data_types
And also here: http://www.techonthenet.com/c_language/variables/index.php
You should define a as
float a;
and replace %d with %f in scanf
scanf("%f", &a);
What should I do?
Read Basics of Formatted Input/Output in C.
Its very simple for int variable we use %d format specifier and if we want float we use %f format specifier. Because according to IEEE int and float bit map format are different.
You are declaring int a which can take only integer value so what you have to do is make it float which is used for numbers having decimal point
float a;
scanf(%f,&a);

Understanding Sign extension

int main()
{
unsigned int b;
signed int a;
char z=-1;
b=z;
a=z;
printf("%d %d",a,b);
}
gives -1 -1. why does no sign extension occur, ALSO, when does it occur?
Sign extension DID occur, but you are printing the results incorrectly. In your printf you specified %d for b, but b is unsigned, you should have used %u to print b.
printf does not know the type of its arguments and uses the format specifies to interpret them.
printf("%d %u",a,b);
Because printf looks at the raw memory, not the type. use %u to print the value as unsigned.
See.
http://ideone.com/Qpcbg

Why does printf print wrong values?

Why do I get the wrong values when I print an int using printf("%f\n", myNumber)?
I don't understand why it prints fine with %d, but not with %f. Shouldn't it just add extra zeros?
int a = 1;
int b = 10;
int c = 100;
int d = 1000;
int e = 10000;
printf("%d %d %d %d %d\n", a, b, c, d, e); //prints fine
printf("%f %f %f %f %f\n", a, b, c, d, e); //prints weird stuff
well of course it prints the "weird" stuff. You are passing in ints, but telling printf you passed in floats. Since these two data types have different and incompatible internal representations, you will get "gibberish".
There is no "automatic cast" when you pass variables to a variandic function like printf, the values are passed into the function as the datatype they actually are (or upgraded to a larger compatible type in some cases).
What you have done is somewhat similar to this:
union {
int n;
float f;
} x;
x.n = 10;
printf("%f\n", x.f); /* pass in the binary representation for 10,
but treat that same bit pattern as a float,
even though they are incompatible */
If you want to print them as floats, you can cast them as float before passing them to the printf function.
printf("%f %f %f %f %f\n", (float)a, (float)b, (float)c, (float)d, (float)e);
a, b, c, d and e aren't floats. printf() is interpreting them as floats, and this would print weird stuff to your screen.
Using incorrect format specifier in printf() invokes Undefined Behaviour
For example:
int n=1;
printf("%f", n); //UB
float x=1.2f;
printf("%d", x); //UB
double y=12.34;
printf("%lf",y); //UB
Note: format specifier for double in printf() is %f.
the problem is... inside printf. the following happens
if ("%f") {
float *p = (float*) &a;
output *p; //err because binary representation is different for float and int
}
the way printf and variable arguments work is that the format specifier in the string e.g. "%f %f" tells the printf the type and thus the size of the argument. By specifying the wrong type for the argument it gets confused.
look at stdarg.h for the macros used to handle variable arguments
For "normal" (non variadac functions with all the types specified) the compiler converts integer valued types to floating point types where needed.
That does not happen with variadac arguments, which are always passed "as is".

Resources