0

Possible Duplicate:
print the float value in integer in C language

I am trying out a rather simple code like this:

float a = 1.5;
printf("%d",a);

It prints out 0. However, for other values, like 1.4,1.21, etc, it is printing out a garbage value. Not only for 1.5, for 1.25, 1.5, 1.75, 1.3125 (in other words, decimal numbers which can be perfectly converted into binary form), it is printing 0. What is the reason behind this? I found a similar post here, and the first answer looks like an awesome answer, but I couldn't discern it. Can any body explain why is this happening? What has endian-ness got to do with t?

Community
  • 1
  • 1
SexyBeast
  • 7,913
  • 28
  • 108
  • 196
  • Yeah I know. That is the link I provided in my question! – SexyBeast Nov 01 '12 at 17:11
  • Take a look into how floating point numbers and integers are stored in bits. – Benedict Cohen Nov 01 '12 at 17:12
  • @Cupidvogel: Yes, I know it is. You're basically asking the same question again because you didn't understand the answer. You should have added a comment on the accepted answer, requesting clarification. – Jon Skeet Nov 01 '12 at 17:13
  • Most of the times I do it, people don't respond. That's why I asked it again. Plus the answer, while concise, is a bit too hard to grasp for me, given I am new to C. So I thought I could do with a detailed explanation. – SexyBeast Nov 01 '12 at 17:15
  • Why are you guys always scouting around for opportunities to close questions, delete questions, downvote, etc? Do you earn points just to be able to do that? Does doing these things give you a sense of power? It is one thing to try and maintain the site's standards by being responsible, it is another thing to go out of the way and let that be your raison d'etre, even when it is very inconvenient to the OP. – SexyBeast Nov 01 '12 at 17:19
  • @Cupidvogel - I can't speak for the downvotes... but as far as voting to close goes, it would be one thing if you tried asking on that other thread and didn't get any responses from anyone. But asking the same question again without trying to get an answer from the thread that you know covers your topic doesn’t seem responsible in my mind. I wouldn't have voted to close if I saw some posts from you there asking for clairification, but it looks like you didn't try. – Mike Nov 01 '12 at 17:28
  • @Cupidvogel If you have a problem with the closure of any particular question, you can raise the issue on [meta](http://meta.stackoverflow.com) and it might get reopened. Ranting about it on the comments is *not* going to help. – NullUserException Nov 01 '12 at 17:35
  • Yeah I know. Ranting there won't help either, so I thought I would rather rant here... – SexyBeast Nov 01 '12 at 17:40
  • @Cupidvogel Ranting *anywhere* won't help. You need to constructively present an argument explaining why it should be reopened. If the community thinks it's a good argument it will be reopened. – NullUserException Nov 01 '12 at 17:46

4 Answers4

2

you're not casting the float, printf is just interpreting it as an integer which is why you're getting seemingly garbage values.

Edit:

Check this example C code, which shows how a double is stored in memory:

int main()
{
    double a = 1.5;
    unsigned char *p = &a;
    int i;

    for (i=0; i<sizeof(double); i++) {
        printf("%.2x", *(p+i));
    }
    printf("\n");
    return 0;
}

If you run that with 1.5 it prints

000000000000f83f

If you try it with 1.41 it prints

b81e85eb51b8f63f

So when printf interprets 1.5 as an int, it prints zero because the 4 LSBs are zeros and some other value when trying with 1.41.

That being said, it is an undefined behaviour and you should avoid it plus you won't always get the same result it depends on the machine and how the arguments are passed.

Note: the bytes are reversed because this is compiled on a little indian machine which means the least significant byte comes first.

iabdalkader
  • 17,009
  • 4
  • 47
  • 74
  • This is not garbage value. For those numbers, it always prints a 0. There is a logic behind it, I want to understand that. – SexyBeast Nov 01 '12 at 17:11
  • @Cupidvogel I didn't say it was garbage, I said it seems so because printf is trying to interpret the float (or double) as int and that's the logic behind it – iabdalkader Nov 01 '12 at 17:15
  • The fact that you always get the same garbage value doesn't mean that there is some logic behind it. Just that the computer executes the same instructions every time. – Bo Persson Nov 01 '12 at 17:16
  • @BoPersson actually there's logic behind it, check the question linked in the OP's question – iabdalkader Nov 01 '12 at 17:17
  • No, this is undefined behaviour. The fact that we might understand what happens on a particular system doesn't mean there is any logic behind it. Zero is also a garbage value! – Bo Persson Nov 01 '12 at 17:20
  • @BoPersson I'm not arguing about that, it is undefined, and I agree we can understand on some level, that's what I think the question is about. same way someone asks about a buffer overflow, it is probably undefined to change the return address on the stack too :) – iabdalkader Nov 01 '12 at 17:23
  • @Cupidvogel check the edit, hope this makes it more clear. – iabdalkader Nov 01 '12 at 17:40
  • 4
    When `printf` is passed the “%d” specification with a `double` argument, `printf` likely tries to interpret *something* as an integer, but you cannot rely on it being the bits of the `double`. In many implementations, floating-point values are passed in different registers from integer values. So, when `printf` attempts to format an argument for the “%d”, it will use bits completely unrelated to the `double` value. – Eric Postpischil Nov 01 '12 at 17:47
  • Thanks. One question, why in little endian machine numbers are counted from LSB? That way, integers will be read reversed, right? – SexyBeast Nov 01 '12 at 17:47
  • BTW, the four LSBs for 1.5 are `f83f`, no? – SexyBeast Nov 01 '12 at 17:48
  • @Cupidvogel they are stored in memory starting with the least significant byte so the four LSBs here are from left to right. so 1.5 is four bytes from the left, see http://en.wikipedia.org/wiki/Endianness – iabdalkader Nov 01 '12 at 17:52
  • @EricPostpischil I did add a note saying that it's undefined, but good point, thanks. – iabdalkader Nov 01 '12 at 17:53
  • @Cupidvogel: 0xf83f are the least significant bits of the common encoding of 1.5, but they are two bytes, not four. – Eric Postpischil Nov 01 '12 at 17:55
1

You don't take care about argument promotions. Because printf is a variadic function, the arguments are promoted:

C11 (n1570), § 6.5.2.2 Function calls
arguments that have type float are promoted to double.

So printf tries to interpret your double variable as an integer type. It leads to an undefined behavior. Just add a cast:

double a = 1.5;
printf("%d", (int)a);
md5
  • 23,373
  • 3
  • 44
  • 93
  • Okay, it gets promoted to double. What happens then? – SexyBeast Nov 01 '12 at 17:16
  • It is incorrect to assert that `printf` tries to interpret the `double` variable as an integer type. The actual behavior is up to the implementation. Commonly, the `double` is passed in a completely different register from where an integer is passed. When `printf` attempts to read an integer argument, it reads the register where it expects to find an integer argument. The contents of that register are likely completely unrelated to the value of the `double`. – Eric Postpischil Nov 01 '12 at 17:43
1

Mismatch of arguments in printf is undefined beahivour either typecast a or use %f

use this way

printf("%d",(int)a);

or

printf("%f",a);
Omkant
  • 9,018
  • 8
  • 39
  • 59
0

d stands for : decimal. so, nevertheless a is float/double/integer/char,.... when you use : "%d", C will print that number by decimal. So, if a is integer type (integer, long), no problem. If a is char : because char is a type of integer, so, C will print value of char in ASCII.

But, the problem appears, when a is float type (float/double), just because if a is float type, C will have special way to read this, but not by decimal way. So, you will have strange result.

Why has this strange result ?

I just give a short explanation : in computer, real number is presented by two part: exponent and a mantissa. If you say : this is a real number, C will know which is exponent, which is mantissa. But, because you say : hey, this is integer. no difference between exponent part and mantissa part -> strange result.

If you want understand exactly, how can know which integer will it print (and of course, you can guess that). You can visit this link : represent FLOAT number in memory in C

If you don't want to have this trange result, you can cast int to float, so, it will print the integer part of float number.

 float a = 1.5;
   printf("%d",(int)a);

Hope this help :)

Community
  • 1
  • 1
hqt
  • 29,632
  • 51
  • 171
  • 250