468,457 Members | 1,578 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 468,457 developers. It's quick & easy.

Confused to printf %f


Someone asked me a question about integer division and printf
yesterday,
I tell him he should do a casting to float/double before you do any
interger division.
But he doesn't think so, so I try to do some example to explain,
However, after some trying,
I confused when I try to do some integer constant division,
I know I should do float division something like 3.0/6.0,
but I'm still confused where the -0.124709 comes for the following
example?
I just add some dummy variables, but the result will show some
different.
did I overflow anything?

The situation is somehow a little different for a different gcc
compiler, it's really wierd.
//example 1
#include <stdio.h>
int main()
{
//double i;
//long a=1,b=4;
printf("%f\n",3/7);
printf("%f\n",5/7);
printf("%.2f\n",5/7);
printf("%f\n",5.0/7.0);
printf("%d\n",4/7);
return 0;
}

-bash-3.00$ gcc z.c
-bash-3.00$ ./a.out
-0.124709
-0.124709
-0.12
0.714286
0

**********************

//example 2:
#include <stdio.h>
int main()
{
double i;
long a=1,b=4;
printf("%f\n",3/7);
printf("%f\n",5/7);
printf("%.2f\n",5/7);
printf("%f\n",5.0/7.0);
printf("%d\n",4/7);
return 0;
}
-bash-3.00$ gcc z.c
-bash-3.00$ ./a.out
0.000000
0.000000
0.00
0.714286
0

********
//example 3:
#include <stdio.h>
int main()
{
double i;
//long a=1,b=4;
printf("%f\n",3/7);
printf("%f\n",5/7);
printf("%.2f\n",5/7);
printf("%f\n",5.0/7.0);
printf("%d\n",4/7);
return 0;
}

-bash-3.00$ gcc -v
Using built-in specs.
Configured with: FreeBSD/i386 system compiler
Thread model: posix
gcc version 3.4.2 [FreeBSD] 20040728

-bash-3.00$ gcc z.c
-bash-3.00$ ./a.out
-0.124709
-0.124709
-0.12
0.714286
0
-bash-3.00$ gcc41 z.c
-bash-3.00$ ./a.out
0.000000
0.000000
0.00
0.714286
0

Thanks for any information!

Jul 29 '06 #1
11 3343
timmu said:
>
Someone asked me a question about integer division and printf
yesterday,
I tell him he should do a casting to float/double before you do any
interger division.
Why?
But he doesn't think so, so I try to do some example to explain,
However, after some trying,
I confused when I try to do some integer constant division,
If you are confused yourself, why did you "tell him" what he should do?
I know I should do float division something like 3.0/6.0,
That isn't a float division.
but I'm still confused where the -0.124709 comes for the following
example?
You lied to the compiler, and it got its revenge.

<snip>
>
//example 1
#include <stdio.h>
int main()
{
//double i;
//long a=1,b=4;
printf("%f\n",3/7);
3 is an int, 7 is an int, and so it's not surprising that 3/7 is an int. But
by using %f, you said to printf: "I'm giving you a double". But you didn't
give it a double. You gave it an int. If you lie to the compiler, it will
wreak its revenge.

Use %d to print ints.

<snip>

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)
Jul 29 '06 #2

Richard Heathfield 寫道:
timmu said:

Someone asked me a question about integer division and printf
yesterday,
I tell him he should do a casting to float/double before you do any
interger division.
^^^^^^^^^
sorry I mean float division.
>
Why?
But he doesn't think so, so I try to do some example to explain,
However, after some trying,
I confused when I try to do some integer constant division,

If you are confused yourself, why did you "tell him" what he should do?
I know I should do float division something like 3.0/6.0,
I really means 3.0/7.0, isn't this double-float division?
That isn't a float division.
but I'm still confused where the -0.124709 comes for the following
example?

You lied to the compiler, and it got its revenge.

<snip>

//example 1
#include <stdio.h>
int main()
{
//double i;
//long a=1,b=4;
printf("%f\n",3/7);

3 is an int, 7 is an int, and so it's not surprising that 3/7 is an int. But
by using %f, you said to printf: "I'm giving you a double". But you didn't
give it a double. You gave it an int. If you lie to the compiler, it will
wreak its revenge.

Use %d to print ints.

<snip>
what I really confused is what compiler doing here.
anyway thx for your information.
>
--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)
Jul 29 '06 #3
timmu said:
>
Richard Heathfield [said]?
>timmu said:
>
Someone asked me a question about integer division and printf
yesterday,
I tell him he should do a casting to float/double before you do any
interger division.
^^^^^^^^^
sorry I mean float division.
Same question. Why cast?

<snip>
>
I really means 3.0/7.0, isn't this double-float division?
It's a division of a double by a double. The result is a double.
but I'm still confused where the -0.124709 comes for the following
example?

You lied to the compiler, and it got its revenge.

<snip>
>
//example 1
#include <stdio.h>
int main()
{
//double i;
//long a=1,b=4;
printf("%f\n",3/7);

3 is an int, 7 is an int, and so it's not surprising that 3/7 is an int.
But by using %f, you said to printf: "I'm giving you a double". But you
didn't give it a double. You gave it an int. If you lie to the compiler,
it will wreak its revenge.

Use %d to print ints.

<snip>

what I really confused is what compiler doing here.
The compiler merely generates a call to printf. It is printf itself which
attempts to evaluate the data you pass to it. If you give it the wrong kind
of data, you shouldn't be surprised if you get the wrong answer.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)
Jul 29 '06 #4

"timmu" <ti****@gmail.comwrote:
printf("%f\n",3/7); // ERROR use %d to print ints
printf("%f\n",5.0/7.0); // OK (prints "0.714286")
printf("%d\n",4/7); // OK (prints "0")
I hope you are aware that in C, the following fractions are ALL
equal to zero?

1/7 2/7 3/7 4/7 5/7 6/7

That's because with integer division, the fractional part is
discarded. If you want to keep the fractional part, you need
to write:

1.0/7.0 2.0/7.0 3.0/7.0 4.0/7.0 5.0/7.0 6.0/7.0

and also use %f instead of %d in your printf() call.

--
Cheers,
Robbie Hatley
East Tustin, CA, USA
lone wolf intj at pac bell dot net
(put "[usenet]" in subject to bypass spam filter)
home dot pac bell dot net slant earnur slant
Jul 29 '06 #5
"timmu" <ti****@gmail.comwrites:
Someone asked me a question about integer division and printf
yesterday,
I tell him he should do a casting to float/double before you do any
interger division.
It depends on what you're trying to do.

The division operator can be applied to either integer or
floating-point operands. ("Integer" refers any integer type: int,
short, long, long long, unsigned char, etc.; "floating-point" refers
to any of float, double, long double.)

If you want to divide integers, divide integers. If you want to
divide floating-point values, do so. There's no general rule that
says you should use one or the other.

In the usual mathematical sense, 3/5 is 0.6; to do that in C, you need
to use floating-point division: 3.0/5.0 (or, for variables rather than
constants, something like (double)x/(double)y). But in C, 3/5 is an
integer division, yielding the value 0 (use the "%" operation if you
want the remainder).

[...]
//example 1
#include <stdio.h>
int main()
{
//double i;
//long a=1,b=4;
printf("%f\n",3/7);
printf("%f\n",5/7);
printf("%.2f\n",5/7);
3/7 and 5/7 are expressions of type int; you need to use "%d" to print
them. Don't try to figure out the results of doing it wrong, just do
it right.

[snip]

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Jul 29 '06 #6
Keith Thompson schrieb:
"timmu" <ti****@gmail.comwrites:
>>Someone asked me a question about integer division and printf
yesterday,
I tell him he should do a casting to float/double before you do any
interger division.

It depends on what you're trying to do.

The division operator can be applied to either integer or
floating-point operands. ("Integer" refers any integer type: int,
short, long, long long, unsigned char, etc.; "floating-point" refers
to any of float, double, long double.)

If you want to divide integers, divide integers. If you want to
divide floating-point values, do so. There's no general rule that
says you should use one or the other.

In the usual mathematical sense, 3/5 is 0.6; to do that in C, you need
to use floating-point division: 3.0/5.0 (or, for variables rather than
constants, something like (double)x/(double)y). But in C, 3/5 is an
integer division, yielding the value 0 (use the "%" operation if you
want the remainder).
As an aside: Some compilers' extensions ignore C semantics in
the following situation:
double foo = 3/5;
then gives you approximately 0.6.
I do no longer have the data about these things but I remember
some gcc 3.x having that "feature" when not invoked with -std=c89,
-ansi, or -std=c99 (more recent gcc versions behave correctly in
this respect) -- a very nasty surprise for a real programme
relying on "foo" having value 0.0 in this case (this came in via
macro) and also little bit embarrassing when trying to teach
students the difference between
3/5
and
3.0/5, 3/5.0, 3.0/5.0
<snip>

Cheers
Michael
--
E-Mail: Mine is an /at/ gmx /dot/ de address.
Jul 29 '06 #7
Michael Mair <Mi**********@invalid.invalidwrites:
[...]
As an aside: Some compilers' extensions ignore C semantics in
the following situation:
double foo = 3/5;
then gives you approximately 0.6.
I do no longer have the data about these things but I remember
some gcc 3.x having that "feature" when not invoked with -std=c89,
-ansi, or -std=c99 (more recent gcc versions behave correctly in
this respect) -- a very nasty surprise for a real programme
relying on "foo" having value 0.0 in this case (this came in via
macro) and also little bit embarrassing when trying to teach
students the difference between
3/5
and
3.0/5, 3/5.0, 3.0/5.0
Hmm. I've just tried it with gcc versions 2.7.2.2, 2.8.1, 2.95.2,
3.0.4, 3.4.4, and 4.1.1; with each of them, it set foo to 0.0.

Program:

#include <stdio.h>
int main(void)
{
double foo = 3/5;
printf("foo = %g\n", foo);
return 0;
}

Command line:

gcc tmp.c -o tmp && ./tmp

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Jul 29 '06 #8
Keith Thompson schrieb:
Michael Mair <Mi**********@invalid.invalidwrites:
[...]
>>As an aside: Some compilers' extensions ignore C semantics in
the following situation:
double foo = 3/5;
then gives you approximately 0.6.
I do no longer have the data about these things but I remember
some gcc 3.x having that "feature" when not invoked with -std=c89,
-ansi, or -std=c99 (more recent gcc versions behave correctly in
this respect) -- a very nasty surprise for a real programme
relying on "foo" having value 0.0 in this case (this came in via
macro) and also little bit embarrassing when trying to teach
students the difference between
3/5
and
3.0/5, 3/5.0, 3.0/5.0

Hmm. I've just tried it with gcc versions 2.7.2.2, 2.8.1, 2.95.2,
3.0.4, 3.4.4, and 4.1.1; with each of them, it set foo to 0.0.

Program:

#include <stdio.h>
int main(void)
{
double foo = 3/5;
printf("foo = %g\n", foo);
return 0;
}

Command line:

gcc tmp.c -o tmp && ./tmp
Maybe it was a "feature" of only one version. I do no longer
have the programmes the students wrote nor do I know the version
of gcc this course went by but I remember the integer division
problem distinctly because I _was_ rather embarrassed at first
before figuring it out.
I found the exercise the translation of which essentially is to
to write a programme reading two ints m and M and do certain things
based on whether m M, M - m < 4, M - m < 8, or else.
Among these things was calculating m/M and (m+M-1)/2.5 for the last
two cases and outputting them -- and, between the lines, remarking
on the difference between integer division and floating point
division... Unfortunately, m/M did not give 0 as expected.

-Michael
--
E-Mail: Mine is an /at/ gmx /dot/ de address.
Jul 29 '06 #9

Robbie Hatley 寫道:
"timmu" <ti****@gmail.comwrote:
printf("%f\n",3/7); // ERROR use %d to print ints
printf("%f\n",5.0/7.0); // OK (prints "0.714286")
printf("%d\n",4/7); // OK (prints "0")

I hope you are aware that in C, the following fractions are ALL
equal to zero?

1/7 2/7 3/7 4/7 5/7 6/7

That's because with integer division, the fractional part is
discarded. If you want to keep the fractional part, you need
to write:

1.0/7.0 2.0/7.0 3.0/7.0 4.0/7.0 5.0/7.0 6.0/7.0

and also use %f instead of %d in your printf() call.
thx for your information,

Of course I know interger divide interger will be integer,
I know double divide double will be double...
I know I should use %f instead of %d if I want to keep the fractional
part...
I knew it when my first year of C programming......

But my friend don't know, I try to explain it to him.
That's why I write the example in origin post.
I wrote the wrong statement because I want to show him "it's wrong!"
Of course I know I should use %f instead of %d...

I just don't satisfied the "you cheat compiler, so it revenge" answer,
I want to know the scene behind these, I want to know why the compiler
generate a different answer
for just adding some dummy variables.

thx informations anyway.
--
Cheers,
Robbie Hatley
East Tustin, CA, USA
lone wolf intj at pac bell dot net
(put "[usenet]" in subject to bypass spam filter)
home dot pac bell dot net slant earnur slant
Aug 2 '06 #10
"timmu" <ti****@gmail.comwrites:
Robbie Hatley 寫道:
>"timmu" <ti****@gmail.comwrote:
printf("%f\n",3/7); // ERROR use %d to print ints
printf("%f\n",5.0/7.0); // OK (prints "0.714286")
printf("%d\n",4/7); // OK (prints "0")

I hope you are aware that in C, the following fractions are ALL
equal to zero?

1/7 2/7 3/7 4/7 5/7 6/7

That's because with integer division, the fractional part is
discarded. If you want to keep the fractional part, you need
to write:

1.0/7.0 2.0/7.0 3.0/7.0 4.0/7.0 5.0/7.0 6.0/7.0

and also use %f instead of %d in your printf() call.

thx for your information,

Of course I know interger divide interger will be integer,
I know double divide double will be double...
I know I should use %f instead of %d if I want to keep the fractional
part...
I knew it when my first year of C programming......

But my friend don't know, I try to explain it to him.
That's why I write the example in origin post.
I wrote the wrong statement because I want to show him "it's wrong!"
Of course I know I should use %f instead of %d...
Great, I'm glad you know this. But that wasn't very clear from your
orginal article. And frankly, it doesn't matter much to us whether
it's you or your friend who didn't now this; we've never met either of
you. We can only answer what you ask.
I just don't satisfied the "you cheat compiler, so it revenge" answer,
I want to know the scene behind these, I want to know why the compiler
generate a different answer
for just adding some dummy variables.
The type of any expression in C (that includes subexpressions) is
almost always determined by the expression itself, not by the context
in which it appears.

In your example:

printf("%f\n", 3/7);

you use "%f" to promise printf that you're going to pass a double, but
then you pass an int.

Why does it print garbage rather than fixing you the error for you?
Because the standard says it's undefined behavior. C99 7.19.6.1p9 says:

If a conversion specification is invalid, the behavior is
undefined. If any argument is not the correct type for the
corresponding conversion specification, the behavior is undefined.

The phrase "the behavior is undefined" means that there are absolutely
no requirements on what the implementation has to do. It can behave
as you might expect, it can produce garbage, it can crash your
program, it can crash your computer, it can reformat your hard drive,
or, as the joke goes, it can make demons fly out of your nose.

Why does your particular implementation behave in some specific way?
I don't know, I don't really care, and you shouldn't either.

The implementation isn't literally getting revenge, it's just behaving
on the *assumption* that you didn't lie to it. Given a "%f" format,
printf will most likely try to print a floating-point value that it
fetches from the location where it would find one if you had passed
one. Since you didn't, it could use the bitwise representation of
your integer value and pretend it's of type double, or it could grab
some piece of garbage from somewhere. If the garbage doesn't
represent a valid value of type double, Bad Things Can Happen. But
different implementations of printf will do different things, and the
details are off-topic here.

Just don't do that.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Aug 2 '06 #11

Keith Thompson 寫道:

Why does it print garbage rather than fixing you the error for you?
Because the standard says it's undefined behavior. C99 7.19.6.1p9 says:

If a conversion specification is invalid, the behavior is
undefined. If any argument is not the correct type for the
corresponding conversion specification, the behavior is undefined.

The phrase "the behavior is undefined" means that there are absolutely
no requirements on what the implementation has to do. It can behave
as you might expect, it can produce garbage, it can crash your
program, it can crash your computer, it can reformat your hard drive,
or, as the joke goes, it can make demons fly out of your nose.

Why does your particular implementation behave in some specific way?
I don't know, I don't really care, and you shouldn't either.

The implementation isn't literally getting revenge, it's just behaving
on the *assumption* that you didn't lie to it. Given a "%f" format,
printf will most likely try to print a floating-point value that it
fetches from the location where it would find one if you had passed
one. Since you didn't, it could use the bitwise representation of
your integer value and pretend it's of type double, or it could grab
some piece of garbage from somewhere. If the garbage doesn't
represent a valid value of type double, Bad Things Can Happen. But
different implementations of printf will do different things, and the
details are off-topic here.

Just don't do that.
thx, now I know the problem is because of different implementations to
a undefine behavior,
really thx for your well explanation.
--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Aug 2 '06 #12

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

7 posts views Thread by Beach Potato | last post: by
29 posts views Thread by Alexander Mahr | last post: by
2 posts views Thread by Kevin C. | last post: by
13 posts views Thread by agentxx04 | last post: by
9 posts views Thread by vijay | last post: by
6 posts views Thread by rahul8143 | last post: by
3 posts views Thread by randomtalk | last post: by
1 post views Thread by linq936 | last post: by
24 posts views Thread by Bill Cunningham | last post: by
1 post views Thread by subhajit12345 | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.