++ / -- operators with floats and doubles

M

my.correo.basura

Yesterday I found in a piece of code a float being incremented with ++.
For some reason (wrong, I guess...) I thought that only integer types
could be incremented that way, and I had never seen floats or doubles
incremented that way before. Just to be sure I did a toy program and
compiled with gcc -ansi -pedantic -Wall and it worked without any error
or warning, showing the correct result.
Is it correct to increment floats or doubles with ++ and --? Is it
defined or am I getting into the realm of undefined behaviour? If it's
correct, can you think of a place where it could be useful?
Many thanks for your time,
Al
 
P

pete

Is it correct to increment floats or doubles with ++ and --? Is it
defined or am I getting into the realm of undefined behaviour?

Any scalar type may be incremented.
You can also increment pointers.
If it's
correct, can you think of a place where it could be useful?

Any time that you might want to increase the value of a float by one.
It could happen, right?
 
J

Jonathan Bartlett

Any time that you might want to increase the value of a float by one.
It could happen, right?

I think the problem with floats is that, depending on the magnitude of
the float, it may be a noop.

Jon
 
M

Malcolm

Jonathan Bartlett said:
I think the problem with floats is that, depending on the magnitude of the
float, it may be a noop.
The other problem is that adding one isn't the same as incrementing.
Incrementing is what you do when you count, adding one is adding a constant
that happens to be unity.
So if I am counting spectators as they pass throught he turnstiles to a
football match, it makes sense to say
count++
every time someone passes through.
On the other hand current rules are that a win is three points, whilst a
draw is one point, and a loss no points. It is not right to say
if(goalsfor == goalsagainst)
points++;
It should be
points += 1;
To make clear that 1 is an externally-defined constant that could change.
The rules could change so that a draw scores zero whilst a loss is minus
one, for example.

Floating point values aren't generally used for counting, that's what we
have integers for. So it doesn't usually make sense to increment them.
 
C

CBFalconer

Jonathan said:
I think the problem with floats is that, depending on the magnitude
of the float, it may be a noop.

float a, b;

a = 0.0;
do {
b = a++;
} while (a != b);
printf("%f\n", a);

and time its execution. It will terminate on any machine known to
me. Then change 'float' to 'double' and try again.
 
P

pete

Malcolm said:
The other problem is that adding one isn't the same as incrementing.

In C, it is.
Floating point values aren't generally used for counting,
that's what we have integers for.
So it doesn't usually make sense to increment them.

I agree.
 
E

E. Robert Tisdale

Jonathan said:
I think the problem with floats is that,
depending on the magnitude of the float, it may be a noop.

You think?
> cat main.c
#include <stdio.h>

int main(int argc, char* argv[]) {
float x = 0.0, y;
do {
y = x;
++x;
} while (y < x);
fprintf(stdout, "x = %f\n", x);
//do {
// y = x;
// } while (y < ++x);
//fprintf(stdout, "x = %f\n", x);
return 0;
}
> gcc -Wall -std=c99 -pedantic -o main main.c
> ./main
x = 16777216.000000
 
A

August Karlstrom

E. Robert Tisdale said:
Jonathan said:
I think the problem with floats is that, depending on the magnitude of
the float, it may be a noop.


You think?
cat main.c
#include <stdio.h>

int main(int argc, char* argv[]) {
float x = 0.0, y;
do {
y = x;
++x;
} while (y < x);
fprintf(stdout, "x = %f\n", x);
//do {
// y = x;
// } while (y < ++x);
//fprintf(stdout, "x = %f\n", x);
return 0;
}
gcc -Wall -std=c99 -pedantic -o main main.c
./main
x = 16777216.000000

If I change the example above to

int main(void)
{
float x = 0.0;

while (x < x + 1) { x++; }
fprintf(stdout, "x = %f\n", x);
return 0;
}

the program doesn't seem to terminate. To me they seem to be more or
less equivalent. Why does it behave differently?

-- August
 
E

E. Robert Tisdale

August said:
If I change the example above to

int main(void) {
float x = 0.0;

while (x < x + 1) { x++; }
fprintf(stdout, "x = %f\n", x);
return 0;
}

the program doesn't seem to terminate.
To me they seem to be more or less equivalent.
Why does it behave differently?

I don't know.
Which computer, operating system and compiler are you using?
Which compiler options are you using?

On my machine, x + 1 (and x < x + 1)
is evaluated using extended precision arithmetic
but x is rounded and stored as double precision
so x increments to 16777216.0 then never changes.
 
W

Walter Roberson

August Karlstrom said:
If I change the example above to

You missed stdio.h ;-)
int main(void)
{
float x = 0.0;

while (x < x + 1) { x++; }
fprintf(stdout, "x = %f\n", x);
return 0;
}
the program doesn't seem to terminate. To me they seem to be more or
less equivalent. Why does it behave differently?

Data point:

With the addition of stdio.h, it terminates for me on SGI IRIX,
using the native compiler or gcc. The termination point is 16777216.
 
C

Christian Bau

August Karlstrom said:
E. Robert Tisdale said:
Jonathan said:
Any time that you might want to increase the value of a float by one.
It could happen, right?


I think the problem with floats is that, depending on the magnitude of
the float, it may be a noop.


You think?
cat main.c
#include <stdio.h>

int main(int argc, char* argv[]) {
float x = 0.0, y;
do {
y = x;
++x;
} while (y < x);

Old value of x has type float. New value of x is calculated with
possibly higher precision than float, but is then rounded to type float.
On typical implementations, 2^24 + 1 cannot be represented as a number
of type float and will be rounded down to 2^24, so your loop will finish
when y = 2^24.

As I thought. That is two to the 24th power.

If I change the example above to

int main(void)
{
float x = 0.0;

while (x < x + 1) { x++; }
fprintf(stdout, "x = %f\n", x);
return 0;
}


Increasing x is done using type float, so x will be stuck at 2^24, as
before. However, in the test "x < x+1", your compiler may evaluate x+1
with higher precision as float, for example double. In that case you
will always be comparing 2^24 < 2^24 + 1, which is always true. Your
loop doesn't finish, but x will be stuck on the same value.
 
A

August Karlstrom

E. Robert Tisdale said:
I don't know.
Which computer, operating system and compiler are you using?

I have an AMD Athlon XP machine with Fedora Core 3 and gcc 3.4.3.
Which compiler options are you using?

gcc -Wall -o test test.c


-- August
 
A

August Karlstrom

Walter said:
You missed stdio.h ;-)

No I do include stdio.h, I just didn't show the whole file:

$ cat test.c
#include <stdio.h>

int main(void)
{
float x = 0.0;

while (x < x + 1) { x++; }

/* float x = 0.0, y; */
/* do { */
/* y = x; */
/* ++x; */
/* } while (y < x); */
/* fprintf(stdout, "x = %f\n", x); */
return 0;
}


-- August
 
A

August Karlstrom

Christian said:
Increasing x is done using type float, so x will be stuck at 2^24, as
before. However, in the test "x < x+1", your compiler may evaluate x+1
with higher precision as float, for example double. In that case you
will always be comparing 2^24 < 2^24 + 1, which is always true. Your
loop doesn't finish, but x will be stuck on the same value.

Okay, so in the first case we are comparing floats, x and y, and in the
second case we compare a float, x, to a number with higher precision, `x
+ 1'? Very subtle indeed.

-- August
 

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

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top