Floating point literals

T

Tony G

I was suprised to find that my compiler included a floating point
library for the following line of code:

x = y * 100 * 0.25;

I thought that the compiler was supposed to evaluate literals at
compile time so that this line would become:

x = y * 25;

I tried looking this up in the standard, but couldn't find any section
that specifically addressed the evaluation of mathematical expressions
in literals.

So is this the way it always works, or does it depend on the compiler?
 
M

Malcolm

Tony G said:
I was suprised to find that my compiler included a floating point
library for the following line of code:

x = y * 100 * 0.25;

I thought that the compiler was supposed to evaluate literals at
compile time so that this line would become:
x = y * 25;

A good compiler ought to resolve constant expressions at compile time.
What it won't do is convert a floating point expression to an integer, so if
you look at the machine code you will see that it probably loads a register
with constant 25 float, then does a floating point multiply with y, which I
presume is an integer.
 
T

Tim Prince

Tony G said:
I was suprised to find that my compiler included a floating point
library for the following line of code:

x = y * 100 * 0.25;

I thought that the compiler was supposed to evaluate literals at
compile time so that this line would become:

x = y * 25;

I tried looking this up in the standard, but couldn't find any section
that specifically addressed the evaluation of mathematical expressions
in literals.

So is this the way it always works, or does it depend on the compiler?
If that's what you want, write it that way:
x=y*(int)(100*.25);

If you wrote
x=100*.25*y;
You would have a reasonable expectation, with left to right evaluation, of
getting
x=25.*y;
 
P

pete

Tim said:
If that's what you want, write it that way:
x=y*(int)(100*.25);

x = y * (100 * 0.25);
.... should do the trick.

But OP's original statement is equivalent to
x = (y * 100) * 0.25;
and it would be wrong for the compiler to combine
the constants into a constant expression that doesn't exist
in the original statement.
 
T

Tony G

I tried several of the suggestions with the following results:

1) x = y * 100 * 0.25; // float lib included
2) x = 100 * 0.25 * y; // float lib included
3) x = y * (100 * 0.25); // float lib included
4) x = y * (int)(100 * 0.25); // float lib NOT included
5) static int x = 100 * 0.25; // float lib NOT included
6) int x = 100 * 0.25; // float lib included

For the first three, apparently the compiler is performing the
multiply at run time because its not recognizing that the result is
going to be converted into an integer (x and y are integers, BTW).
Adding the cast on 4 is enough of a hint for the compiler to catch on
and do the math at compile time. Using the multiply in a static
initializer in 5 forces the compiler to try to fully evaluate the
expression at compile time since the expression must be constant. But
since an initializer for a local doesn't have to be constant, for 6
the compiler performs the multiply at run time.

So at least now I understand what's going on. But I still don't know
what the C standard says about it. I'm pretty sure that 5 will either
work or generate an error message (i.e., "Initializer must be
constant..."). But can I count on 4 always working, or is it
implementation dependant?
 
P

pete

Tony said:
But I still don't know what the C standard says about it.
I'm pretty sure that 5 will either
work or generate an error message (i.e., "Initializer must be
constant..."). But can I count on 4 always working, or is it
implementation dependant?

Unspecified.
A program is allowed to evaluate it's constant expressions
at compile time or run time.
 
W

William Hughes

I tried several of the suggestions with the following results:

1) x = y * 100 * 0.25; // float lib included
2) x = 100 * 0.25 * y; // float lib included
3) x = y * (100 * 0.25); // float lib included
4) x = y * (int)(100 * 0.25); // float lib NOT included
5) static int x = 100 * 0.25; // float lib NOT included
6) int x = 100 * 0.25; // float lib included

For the first three, apparently the compiler is performing the
multiply at run time because its not recognizing that the result is
going to be converted into an integer (x and y are integers, BTW).

It is just as likely that the compiler is performing the multiply
at compile time, but not performing the cast at compile time.
In general int(x*a) is not equal to x*int(a) even if x is an integer.
It is a lot to ask of the compiler that is recognize that
even though 25. is a floating point constant its value is
integral. The float lib is still needed to compute
x*25.
Adding the cast on 4 is enough of a hint for the compiler to catch on
and do the math at compile time.

Or possibly allows the cast from 25. to 25 which removes the need
for the float lib.

Using the multiply in a static
initializer in 5 forces the compiler to try to fully evaluate the
expression at compile time since the expression must be constant.
But since an initializer for a local doesn't have to be constant, for 6
the compiler performs the multiply at run time.

The compiler could perform this multiply at run time but it does not
have to. Again you seem to be assuming that if the float lib is loaded
the multiply must be done at run time. This may or may not be true.
So at least now I understand what's going on. But I still don't know
what the C standard says about it. I'm pretty sure that 5 will either
work or generate an error message (i.e., "Initializer must be
constant..."). But can I count on 4 always working, or is it
implementation dependant?

If you mean can you count on 4 leading to x having the value 25*y, the answer
is yes. If you mean can you count on 4 forcing the evaluation of (100 * 0.25)
at compile time the answer is no, the compiler may evaluate
this at compile time but does not have to. If you mean can you count on 5
leading to the float lib not being loaded the answer is no. The standard
is silent on when the float lib should be loaded, or indeed if there
is such a beast as a float lib in the first place. The implementation
could choose to load the float lib whenever there is a full moon.
More likely in practice, the implementation may use heuristics to
decide when to load float lib. Since not loading float lib when
needed is a far more serious error than loading float lib when not
needed the heuristics will be chosen to favour the latter.

-William Hughes
 

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
474,140
Messages
2,570,810
Members
47,357
Latest member
sitele8746

Latest Threads

Top