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! 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)
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)
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)
"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
"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.
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.
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.
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.
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
"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.
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.
This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics
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...
|
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...
|
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...
|
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...
|
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...
|
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...
|
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...
|
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.");
|
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);}
|
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
|
by: nemocccc |
last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
|
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...
|
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,...
|
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,...
|
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...
|
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...
|
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,...
|
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...
| |