473,406 Members | 2,369 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,406 software developers and data experts.

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 3852
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 thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

7
by: Beach Potato | last post by:
I guess I've been out of C++ for a while, since right now I don't seem to get a simple solution for overriding inherited constrictors. What worked in Borland C++ & Pascal (and Java, if I remember...
29
by: Alexander Mahr | last post by:
Dear Newsgroup, I'm somehow confused with the usage of the static keyword. I can see two function of the keyword static in conjunction with a data member of a class. 1. The data member...
2
by: Kevin C. | last post by:
Can someone explain why the file output produces all zeros? It seems to work fine in memory (e.g. passing char pointers to printf) but when I output the file, it comes out as zeros. Bookkeeping...
13
by: agentxx04 | last post by:
Hi. Our assignment was to creat a program that can find the average, median & mode of a #of integers. Here's my program: #include<stdio.h> int main() { int item; int a, b, t, mode; int...
9
by: vijay | last post by:
Hello, I am new to C Programming and just started reading K&R. I was about to finish the pointers chapter but got very confused with: 1. int arr; >From what I have read, arr is a pointer to...
6
by: rahul8143 | last post by:
hello, I am really confused over following for code snippets. No problem that they are working codes but how? how they are evaluated by compiler? It will be my pleasure if you explain me all...
3
by: randomtalk | last post by:
hello everyone! Well, recently i've been trying to pick up c and see what is pointer all about (been programming in lisp/python for the better part of my last two years).. mmm.. I'm currently...
1
by: linq936 | last post by:
Hi, I read in many places that the string to be outputted by printf() must be ending with newline, for example, it should be printf("Hello World.\n"); instead of printf("Hello World.");
24
by: Bill Cunningham | last post by:
It is very easy to see what I am trying to do with this code: #include <stdio.h> main(){ char name; printf ("Enter -"); fflush (stdout); fgets (name,200,stdin); printf("is? ",name);}
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development projectplanning, coding, testing,...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.