what is happening in C when increment this way?

P

puzzlecracker

If you run this program, it will give very unexpected results. Can
anyone explain the nature of this anamaly? (also what is the function
call [and library to include linux/windows] to execute 'pause');

#include<stdio.h>

//void pause(){ unsigned long i=0; while(i++<10000000); }

int main(){
float i;

for(i=0;i<100;i+=0.1) // pay attention
{ // pause();
printf("%d\n",i);
}

printf("\n");
return 0;


}
 
J

John Valko

puzzlecracker said:
If you run this program, it will give very unexpected results. Can
anyone explain the nature of this anamaly? (also what is the function
call [and library to include linux/windows] to execute 'pause');

printf("%d\n",i);

This line is the problem. The format specifier for printifng floats
(and doubles) is %f (or %e or %g).

--John
 
B

Big K

puzzlecracker said:
If you run this program, it will give very unexpected results. Can
anyone explain the nature of this anamaly? (also what is the function
call [and library to include linux/windows] to execute 'pause');

#include<stdio.h>


int main(){
float i;

for(i=0;i<100;i+=0.1) // pay attention
{ // pause();
printf("%d\n",i);

Use %f instead of %d (%d is to be used only for decimal integers).
You're getting weird results by invoking undefined behaviour
(conversion specified mismatch with corresponding argument).
 
P

puzzlecracker

John said:
puzzlecracker said:
If you run this program, it will give very unexpected results. Can
anyone explain the nature of this anamaly? (also what is the function
call [and library to include linux/windows] to execute 'pause');

printf("%d\n",i);

This line is the problem. The format specifier for printifng floats
(and doubles) is %f (or %e or %g).

--John


I mean %f actually ---- it does print but it gets weirder
try it withj %f
 
J

John Valko

puzzlecracker said:
John Valko wrote:

I mean %f actually ---- it does print but it gets weirder
try it withj %f

Please explain what you mean by "weirder"
 
P

puzzlecracker

John said:
Please explain what you mean by "weirder"

run the program and tell me if output was expected. I traced the
problem but cannot yet explain it. IT has to do with the way floating
point numbers are represented.
 
M

Martin Ambuhl

puzzlecracker said:
If you run this program, it will give very unexpected results.

1) There is nothing unexpected about using the wrong (integer) specifier
to output floating point values.
2) There is nothing unexpected about the results of using loops with
floating point counters with inexact increments.

Unpredictable across platforms, yes, but not unexpected.
Can
anyone explain the nature of this anamaly?

1) Anyone who can read the documentation (or a basic C text) for printf can.
2) Anyone who knows anything about floating point representation can.

There are some questions in the FAQ relating to your question.
See, for example
<http://www.eskimo.com/~scs/C-faq/q14.4.html>.
Always check the FAQ before posting. Haven't you been told this before?
I applaud your attempt to expand your vocabulary, but the word is "anomaly."
(also what is the function
call [and library to include linux/windows] to execute 'pause');
It is system-specific.
 
J

Jesse Meyer

puzzlecracker said:
If you run this program, it will give very unexpected results. Can
anyone explain the nature of this anamaly? (also what is the function
call [and library to include linux/windows] to execute 'pause');

float i;

for(i=0;i<100;i+=0.1) // pay attention
{
printf("%d\n",i);
}

Ill ignore the rather obvious printf problem and ask:

How many times are you expecting this loop to execute?

I hope you weren't expecting 1000 times.


The C FAQ, Question 14.1 may give you a clue why:

http://www.eskimo.com/~scs/C-faq/q14.1.html

Try also question 14.4

http://www.eskimo.com/~scs/C-faq/q14.4.html


PS: If you post via google, I've heard that groups.google.ca
won't mangle indentation levels.
 
P

puzzlecracker

Martin said:
puzzlecracker said:
If you run this program, it will give very unexpected results.

1) There is nothing unexpected about using the wrong (integer) specifier
to output floating point values.
2) There is nothing unexpected about the results of using loops with
floating point counters with inexact increments.

Unpredictable across platforms, yes, but not unexpected.
Can
anyone explain the nature of this anamaly?

1) Anyone who can read the documentation (or a basic C text) for printf can.
2) Anyone who knows anything about floating point representation can.

There are some questions in the FAQ relating to your question.
See, for example
<http://www.eskimo.com/~scs/C-faq/q14.4.html>.
Always check the FAQ before posting. Haven't you been told this before?
I applaud your attempt to expand your vocabulary, but the word is "anomaly."
(also what is the function
call [and library to include linux/windows] to execute 'pause');
It is system-specific.

#include<stdio.h>

//void pause(){ unsigned long i=0; while(i++<10000000); }

int main(){
float i;

for(i=0;i<100;i+=0.1) // pay attention
{ // pause();
printf("%d\n",i);
}

printf("\n");
return 0;


}

YOU ARE WRONG - it not SYSTEM NOR COMPILER SPECIFIC-- it is the way
floats represented.
same anOmaly is in java as well as C#, c++ I checked
thx for trying though
 
M

Martin Ambuhl

puzzlecracker said:
Martin Ambuhl wrote:
(also what is the function
call [and library to include linux/windows] to execute 'pause');

It is system-specific.
YOU ARE WRONG - it not SYSTEM NOR COMPILER SPECIFIC-- it is the way
floats represented.

Pardon me for asking, but how long have you been an idiot? The only
reference to "system specific" is the above answer to the above
question, and I never mentioned "compiler specific." Just why do you
think the non-standard function pause() might have anything to do with
the representation of floats?
 
C

CBFalconer

puzzlecracker said:
If you run this program, it will give very unexpected results. Can
anyone explain the nature of this anamaly? (also what is the function
call [and library to include linux/windows] to execute 'pause');

#include<stdio.h>

//void pause(){ unsigned long i=0; while(i++<10000000); }

int main(){
float i;

for(i=0;i<100;i+=0.1) // pay attention
{ // pause();
printf("%d\n",i);
}

printf("\n");
return 0;

}

Don't use C99 comments in C90 code. The result:

[1] c:\c\junk>gcc junk.c
junk.c:3: parse error before '/' token
junk.c: In function `main':
junk.c:8: parse error before '/' token
junk.c:10: warning: int format, double arg (arg 2)
junk.c: At top level:
junk.c:12: parse error before string constant
junk.c:12: warning: type defaults to `int' in declaration of
`printf'
junk.c:12: warning: conflicting types for built-in function
`printf'
junk.c:12: ISO C forbids data definition with no type or storage
class

After removing those execrences we get:

[1] c:\c\junk>gcc junk.c
junk.c: In function `main':
junk.c:8: warning: int format, double arg (arg 2)

and lying to the compiler about the type of an argument to a
variadic function is undefined behaviour.

There is no "pause" function in standard C.
 
C

CBFalconer

.... snip ...
I mean %f actually ---- it does print but it gets weirder
try it withj %f

Seems perfectly normal to me. I get:

0.000000
0.100000
..... snip ....
99.799049
99.899048
99.999046

What do you think the exact value of your 0.1 constant really is?
 
N

Neil Kurzman

What people are trying to say is in floating point
float f;

f= 1.0 + 1.0;

And some how f=1.99999999 (newbie gasp and old timers say So?)
so in floating point 1+1 <>2
The is how floating point math is in all languages on all compilers.
 
J

jcoffin

Neil said:
What people are trying to say is in floating point
float f;

f= 1.0 + 1.0;

And some how f=1.99999999 (newbie gasp and old timers say So?)
so in floating point 1+1 <>2
The is how floating point math is in all languages on all compilers.

You have the right general idea, but unfortunately your example is
completely wrong.

There is some range within which floating point numbers can represent
integers precisely (for float, this will typically be around +/- 2^24).
Outside this range, there will be a gap between one integer and the
next larger one that can be represented. As the magnitude of the number
grows, so does the size of the gap from one number to the next, so the
total number of digits that can be represented remains roughly constant
(the amount of data that can be represented does remain constant, but
the binary to decimal conversion can vary the number of decimal digits
the number converts to, and when you look at it in decimal, you often
get a half digit of precision -- i.e. a final digit that's not
completely right, but not complete wrong either -- e.g if it's a five,
the correct value might really be four or six, but definitely isn't 1
or 9).

Toward the center of the range, (e.g. between -1 and 1) you have more
data available than is necessary to represent an integer. In this case,
some places after the decimal point represent real data.

As soon as we get to fractions, however, we run into another problem:
we're representing the number as a binary fraction. The only fractions
that can be represented precisely are those whose prime factorizations
contain only 2. Otherwise, we end up with a repeating fraction of some
sort that can't be represented precisely in any finite number of bits.

So, 1.0f + 1.0f will always equal exactly 2.0f -- but if you continue
adding 1.0f often enough, you'll reach a point at which it no longer
changes the value of the result AT ALL! For example, a loop like this:

float current = 1.0f, previous = 0.0f;

while (current != previous) {
previous = current;
current += 1.0;
}

will exit in well under a second on a typical machine.

With doubles you get the same basic characteristics, though with a lot
more precision, including a much larger range within which integers can
all be represented precisely.

One other minor detail: by default, C and C++ output functions will
print either a float or a double to the same precision. If memory
serves, the default is 5 digits. More or less by chance, this happens
to be about the limit a typical float can represent, so almost ANY sort
of error in a float will show up immediately.

As mentioned above, a double typically has quite a bit more precsion --
around 15 digits in fact. This means that if you print out with the
default precision, a double will look like it's giving a precisely
correct result until or unless your result has gotten far enough off to
destroy the precision of roughly 2/3rds of its digits.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,767
Messages
2,569,571
Members
45,045
Latest member
DRCM

Latest Threads

Top