Trouble with integer floating point conversion

R

rembremading

Hi all!

The following piece of code has (for me) completely unexpected behaviour.
(I compile it with gcc-Version 4.0.3)
Something goes wrong with the integer to float conversion.
Maybe somebody out there understands what happens.
Essentially, when I subtract the (double) function value GRID_POINT(2) from
a variable which has been assigned the same value before this gives a
non-zero result and I really do not understand why.

The program prints
5.000000000000000000e-01; -2.775557561562891351e-17;
0.000000000000000000e+00

And the comparison
if(temp1==GRID_POINT(2))
has negative outcome.

When I replace
((double)(i)) by 2.0
everything behaves as expected. So the output is
5.000000000000000000e-01; 0.000000000000000000e+00; 0.000000000000000000e+00

But: even if the integer to float conversion is inexact (which, I think,
should not be the case) something like
temp1 = GRID_POINT(2);
temp3 = temp1-GRID_POINT(2);
should still result in temp3==0.0, whatever function GRID_POINT does.

What do You think?

Thank you!

---------------------------------------------------
#include <stdio.h>

double GRID_POINT(int i);

double GRID_POINT(int i)
{
return ( 0.1 + ( (80.1-0.1)/(400.0) )*((double)(i)) );
}

int main (void) {

double temp1, temp2, temp3;

temp1 = GRID_POINT(2);
temp2 = GRID_POINT(2);
temp3 = temp1-GRID_POINT(2);

printf("%.18e; %.18e; %.18e\n", temp1, temp3, temp1-temp2 );

if(temp1==GRID_POINT(2)){
printf("these two are equal\n");
}

return 0;
}
---------------------------------------------------
 
R

rembremading

I should add, that the problem, described below, does not occur, when the
Intel compiler is used.
When compiling with gcc I don't use any optimisation options.
This does not solve my problem, however.
 
J

jacob navia

rembremading said:
I should add, that the problem, described below, does not occur, when the
Intel compiler is used.
When compiling with gcc I don't use any optimisation options.
This does not solve my problem, however.

The Intel compiler sets probably the precision of the machine
to 64 bits.

The gcc compiler and other compilers like lcc-win set the precision
of the machine at 80 bits.

This means that the calculations are done using MORE precision
than double precision what can lead to different results.

You can set the precision of the machine yourself to 64 bits
within the gcc run time.
 
F

Francine.Neary

The Intel compiler sets probably the precision of the machine
to 64 bits.

The gcc compiler and other compilers like lcc-win set the precision
of the machine at 80 bits.

This means that the calculations are done using MORE precision
than double precision what can lead to different results.

You can set the precision of the machine yourself to 64 bits
within the gcc run time.

Much better to assume only what the Standard guarantees about floating-
point operations, and use third-party libraries like GMP if you need
extra precision.
 
J

jacob navia

Much better to assume only what the Standard guarantees about floating-
point operations, and use third-party libraries like GMP if you need
extra precision.

The standard doesn't guarantee *anything* at all.

Myself I *thought* that the standard implied IEEE 754 but people
here pointed me to an obscure sentence that allows an implementation to
get away with that too, and implement some other kind of weird
floating point.

Since the standard doesn't force even IEEE754, there is *nothing*
the C language by itself can guarantee the user.

To come back to the original poster problem.

The machine has two ways of floating point operations:
1) 80 bits intenral precision
b) 64 bits internal precision.

Microsoft and Intel use (2), gcc and lcc-win use (1).

This means that when values are stored only in floating point
registers and NOT stored into memory, the same computation can
yield *different* results as the user has noticed.

The final fix to this is to set the machine to use only 64 bits
precision ONLY. This can be done with a few assembler instructions.
lcc-win rpovides a function to do this, maybe gcc does too.

Another possibility is to use the floating point environment functions
to read the environment, figure out where the precision bit
is, and then modify that and write it back to the floating
point unit.


 
F

Flash Gordon

jacob navia wrote, On 12/12/07 21:50:
The standard doesn't guarantee *anything* at all.

Wrong again. Try actually reading the standard which has a section
entitled "Numerical limits" which is split in to two parts. Guess what
the part that is not describing integer types is about.
Myself I *thought* that the standard implied IEEE 754 but people
here pointed me to an obscure sentence that allows an implementation to
get away with that too, and implement some other kind of weird
floating point.

I would not call the introduction to a section obscure myself.
Since the standard doesn't force even IEEE754, there is *nothing*
the C language by itself can guarantee the user.

Are you seriously trying to claim that the only way to provide any form
of guarantee on floating point is to enforce IEEE754?
To come back to the original poster problem.

The machine has two ways of floating point operations:
1) 80 bits intenral precision
b) 64 bits internal precision.

Microsoft and Intel use (2), gcc and lcc-win use (1).

This means that when values are stored only in floating point
registers and NOT stored into memory, the same computation can
yield *different* results as the user has noticed.

The final fix to this is to set the machine to use only 64 bits
precision ONLY. This can be done with a few assembler instructions.
lcc-win rpovides a function to do this, maybe gcc does too.

Of course, changing the mode in which the processor operates behind the
back of the compiler can cause interesting effects. Interesting as in
the ancient Chinese curse, that is.
Another possibility is to use the floating point environment functions
to read the environment, figure out where the precision bit
is, and then modify that and write it back to the floating
point unit.

Or better yet assume only what is guaranteed or use a library designed
to provide better guarantees if you need them. Or limit yourself to
compilers that guarantee the behaviour you require if it is acceptable
to so limit yourself.
 
J

jameskuyper

Flash said:
jacob navia wrote, On 12/12/07 21:50: ....

Are you seriously trying to claim that the only way to provide any form
of guarantee on floating point is to enforce IEEE754?

The C standard does say a lot of important things about floating point
operations, but everything useful it says can be rendered irrelevant
by section 5.2.4.2.2:
"The accuracy of the floating-point operations (+, -, *, /) and of the
library functions in <math.h> and <complex.h> that return floating-
point results is implementation defined. The implementation may state
that the accuracy is unknown."

Technically, a conforming implementation of C could specify that the
accuracy is +/-200%. More plausibly, an implementation could specify
an accuracy that is nowhere near to being sufficient for a given
application. For serious numerical work, the scariest possibility is
that the implementation may simply choose to document that "the
accuracy is unknown".

In C99, if __STD_IEC_559__ is defined by the implementation, the
accuracy of floating point operations and functions is much more
tightly constrained (IEC 559:1989 is an alternate name for the same
standard as ANSI/IEEE754-1985). I wouldn't recommend using C floating
point types for serious numerical work without some such promise.
 
P

Peter Nilsson

rembremading said:
Hi all!

The following piece of code has (for me) completely
unexpected behaviour.
(I compile it with gcc-Version 4.0.3)
Something goes wrong with the integer to float conversion.

Did you apply -ffloat-store?

Without that (and others), gcc is not a conforming compiler
on many architectures.
 
C

CBFalconer

Flash said:
jacob navia wrote, On 12/12/07 21:50:
.... snip ...


Of course, changing the mode in which the processor operates behind
the back of the compiler can cause interesting effects. Interesting
as in the ancient Chinese curse, that is.


Or better yet assume only what is guaranteed or use a library
designed to provide better guarantees if you need them. Or limit
yourself to compilers that guarantee the behaviour you require if
it is acceptable to so limit yourself.

All this silly arguing, and nobody bothers mentioning the
applicable section of the standard. From N869, about float.h:

[#10] The values given in the following list shall be
replaced by implementation-defined constant expressions with
(positive) values that are less than or equal to those
shown:

-- the difference between 1 and the least value greater
than 1 that is representable in the given floating
point type, b1-p

FLT_EPSILON 1E-5
DBL_EPSILON 1E-9
LDBL_EPSILON 1E-9

-- minimum normalized positive floating-point number,
bemin-1

FLT_MIN 1E-37
DBL_MIN 1E-37
LDBL_MIN 1E-37
 
F

Flash Gordon

CBFalconer wrote, On 13/12/07 03:44:
All this silly arguing, and nobody bothers mentioning the
applicable section of the standard. From N869, about float.h:

<snip>

Actually, I *did* mention the applicable section of the standard. Well,
I mentioned the parent section, Numerical Limits, by name. Specifically,
I said in material you have snipped:

| Wrong again. Try actually reading the standard which has a section
| entitled "Numerical limits" which is split in to two parts. Guess what
| the part that is not describing integer types is about.

As someone else has pointed out it does not guarantee a lot about the
accuracy of calculations, only what the representation is capable of. So
it is not much, just more than nothing.
 
J

jacob navia

Flash said:
Wrong again. Try actually reading the standard which has a section
entitled "Numerical limits" which is split in to two parts. Guess what
the part that is not describing integer types is about.

This is typical of the "regulars". Talk to say nothing. That part
of the standard has not anything to say about the precision
of intermediate results (what we are talking about here)
but about how big the LIMITS of the floating point representation
are.

To the subject of precision, the standard says:
<quote>
The accuracy of the floating-point operations (+, -, *, /) and of the
library functions in <math.h> and <complex.h> that return floating-point
results is implementation defined.

The implementation may state that the accuracy is unknown
<end quote>

i.e. IT CONFIRMS what I am saying. There aren't any guarantees at all.
I would not call the introduction to a section obscure myself.


Are you seriously trying to claim that the only way to provide any form
of guarantee on floating point is to enforce IEEE754?

If there isn't even an accepted standard that is enforced, how
can you guarantee anything.

Question Mr "flash"

How could the standard guarantee ANYTHING about the precision of
floating point calculations when it doesn't even guarantee a common
standard?

Yes I am seriously saying that the absence of an enforced standard
makes any guarantee IMPOSSIBLE.

Please prove the contrary.
Of course, changing the mode in which the processor operates behind the
back of the compiler can cause interesting effects. Interesting as in
the ancient Chinese curse, that is.

How learned you are Mr Gordon....

Anything else?

Like all the "regulars", you speak with word games. If you have anything
else to propose please say it clearly. If not, say clearly
what "adverse side effects" would happen with my proposition.
Or better yet assume only what is guaranteed

NOTHING is guaranteed by the standard. See above
or use a library designed
to provide better guarantees if you need them.

This is stupid since the library can't change the way the program is
compiled. If you substitute the call to the user function by a call to
a library function the problem remains THE SAME. You fail to grasp what
the problem is.

Or limit yourself to
compilers that guarantee the behaviour you require if it is acceptable
to so limit yourself.

This is not necessary, you just change the precision that's all!

This is an example of how the "regulars" spread nonsense just with the
only objective of "contradicting jacob" as they announced here
yesterday.
 
K

Keith Thompson

jacob navia said:
Flash Gordon wrote: [...]
(I think jacob wrote the above; the attribution was snipped.)

Are you seriously trying to claim that the only way to provide any
form of guarantee on floating point is to enforce IEEE754?

If there isn't even an accepted standard that is enforced, how
can you guarantee anything.
[...]

How could the standard guarantee ANYTHING about the precision of
floating point calculations when it doesn't even guarantee a common
standard?

Yes I am seriously saying that the absence of an enforced standard
makes any guarantee IMPOSSIBLE.

First of all, the C standard says that accuracy of floating-point
operations is implementation-defined, though the implementation is
allowed to say that the accuracy is unknown. This doesn't refute
jacob's claim, but it does mean that a particular implementation is
allowed to make guarantees that the standard doesn't make.

It's entirely possible for a language standard to make firm guarantees
about floating-point accuracy without mandating adherence to one
specific floating-point representation. For example, the Ada standard
has a detailed parameterized floating-point model with specific
precision requirements; Ada's requirements are satisfied by an IEEE
754 implementation, but can also be (and have been) satisfied by a
number of other floating-point representations. For example, in Ada
1.0 + 1.0 is guaranteed to be exactly equal to 2.0.

The C standard could have followed the same course (and since it was
written several years after the first Ada standard, I'm not entirely
sure why it didn't). But instead, the authors of the C standard chose
to leave floating-point precision issues up to each implementation.

In practice, each C implementation and each Ada implementation usually
just uses whatever floating-point representation and operations are
provided by the underlying hardware. (Exception: some systems
probably use software floating-point, and some others might need to do
some tweaking on top of what the hardware provides.) In most cases,
the precision provided by the hardware is as good as what the language
standard *could* have guaranteed.

Yes, jacob, it's true that the C standard makes no guarantees about
floating-point precision. It does make some guarantees about
floating-point range, which seems to contradict your claim above that
"there is *nothing* the C language by itself can guarantee the user".
(Perhaps in context it was sufficiently clear that you were talking
only about precision; I'm not going to bother to go back up the thread
to check.)

As for *why* the C standard doesn't require IEEE 754, there have been
plenty of computers that support other representations, and it would
have been absurd for the C standard to require IEEE 754 on systems
that don't provide it. (Examples: VAX, older Cray vector systems, and
IBM mainframes each have their own floating-point formats; there are
undoubtedly more examples.) The intent of IEEE 754 is to define a
single universal floating-point standard, and we're headed in that
direction, but we're not there yet -- and we certainly weren't there
when the C89 standard was being written.

[...]
This is an example of how the "regulars" spread nonsense just with the
only objective of "contradicting jacob" as they announced here
yesterday.

Tedious rant ignored.
 
Y

ymuntyan

jacob navia said:
Flash Gordon wrote: [...]
Since the standard doesn't force even IEEE754, there is *nothing*
the C language by itself can guarantee the user.

(I think jacob wrote the above; the attribution was snipped.)


If there isn't even an accepted standard that is enforced, how
can you guarantee anything.
[...]

How could the standard guarantee ANYTHING about the precision of
floating point calculations when it doesn't even guarantee a common
standard?
Yes I am seriously saying that the absence of an enforced standard
makes any guarantee IMPOSSIBLE.

First of all, the C standard says that accuracy of floating-point
operations is implementation-defined, though the implementation is
allowed to say that the accuracy is unknown. This doesn't refute
jacob's claim, but it does mean that a particular implementation is
allowed to make guarantees that the standard doesn't make.

It's entirely possible for a language standard to make firm guarantees
about floating-point accuracy without mandating adherence to one
specific floating-point representation. For example, the Ada standard
has a detailed parameterized floating-point model with specific
precision requirements; Ada's requirements are satisfied by an IEEE
754 implementation, but can also be (and have been) satisfied by a
number of other floating-point representations. For example, in Ada
1.0 + 1.0 is guaranteed to be exactly equal to 2.0.

The C standard could have followed the same course (and since it was
written several years after the first Ada standard, I'm not entirely
sure why it didn't). But instead, the authors of the C standard chose
to leave floating-point precision issues up to each implementation.

In practice, each C implementation and each Ada implementation usually
just uses whatever floating-point representation and operations are
provided by the underlying hardware. (Exception: some systems
probably use software floating-point, and some others might need to do
some tweaking on top of what the hardware provides.) In most cases,
the precision provided by the hardware is as good as what the language
standard *could* have guaranteed.

Yes, jacob, it's true that the C standard makes no guarantees about
floating-point precision. It does make some guarantees about
floating-point range, which seems to contradict your claim above that
"there is *nothing* the C language by itself can guarantee the user".
(Perhaps in context it was sufficiently clear that you were talking
only about precision; I'm not going to bother to go back up the thread
to check.)

You quoted it: "How could the standard guarantee ANYTHING about
the precision of floating point calculations..."
[...]
This is an example of how the "regulars" spread nonsense just with the
only objective of "contradicting jacob" as they announced here
yesterday.

Tedious rant ignored.

So you just demonstrated that JN's paranoia is not *quite* paranoia.
Your post
is exactly what he refers to (using strong words like "nonsense",
since JN
gets pretty emotional in this grand war).

World will stop, and all newbies will get confused and die if you stop
arguing
with Jacob, sure. You simlpy have to do it again and again. Even when
you don't
have a point! Oh well.
 
J

jacob navia

So you just demonstrated that JN's paranoia is not *quite* paranoia.
Your post
is exactly what he refers to (using strong words like "nonsense",
since JN
gets pretty emotional in this grand war).

Yes, I am getting more and more nervous. You are right, I will
try to keep a more low profile attitude.
 
M

Mark Bluemel

Peter said:
Did you apply -ffloat-store?

I did that on the testcase. It didn't help.

The manual page states for -ffloat-store
" Do not store floating point variables in registers, and inhibit other
options that might change whether a floating point value is taken from
a register or memory."

It doesn't appear to alter how a floating point return value from a
function (presumably in a register) is handled. This is probably covered
by the further comment in the manual page :-

... "a few programs rely on the precise definition of IEEE floating
point. Use -ffloat-store for such programs, _after modifying them to
store all pertinent intermediate computations into variables_."

So to answer the original poster (As best as I understand it) -
This is due to the register holding the return value having greater
precision than the defined precision of "double".
 
M

Mark Bluemel

rembremading said:
Hi all!

The following piece of code has (for me) completely unexpected behaviour.
(I compile it with gcc-Version 4.0.3)
Something goes wrong with the integer to float conversion.
Maybe somebody out there understands what happens.
Essentially, when I subtract the (double) function value GRID_POINT(2) from
a variable which has been assigned the same value before this gives a
non-zero result and I really do not understand why.

http://www.network-theory.co.uk/docs/gccintro/gccintro_70.html has a
detailed discussion...
 
J

James Kuyper

jacob said:
....
To the subject of precision, the standard says:
<quote>
The accuracy of the floating-point operations (+, -, *, /) and of the
library functions in <math.h> and <complex.h> that return floating-point
results is implementation defined.

The implementation may state that the accuracy is unknown
<end quote>

i.e. IT CONFIRMS what I am saying. There aren't any guarantees at all.

There are no guarantees about the accuracy for implementations that
don't pre-define __STDC_IEC_559__. The Numerical Limits section he cited
does, however, contain a great many guarantees about things other than
the accuracy.

....
This is stupid since the library can't change the way the program is
compiled. If you substitute the call to the user function by a call to
a library function the problem remains THE SAME. You fail to grasp what
the problem is.

A library can't change the way that floating point math is handled by
the compiler in your own functions. However, a large part of the
guarantees that you get only if __STDC_IEC_559__ is pre-defined by the
implementation are guarantees about what the standard library's math.h
and tgmath.h functions do. Changing which library you use can affect
that issue, even if it doesn't help internally. If that seems like small
consolation, keep in mind that it is precisely those functions where an
implementation is most likely to have deficient accuracy. Getting
ordinary floating point math right is generally much easier than getting
those functions right; for instance, naive implementations of the sin()
function can behave much worse than they should when passed large
argument values.
 
J

James Kuyper

You quoted it: "How could the standard guarantee ANYTHING about
the precision of floating point calculations..."

Well, actually, the numerical limits section does specify the precision.
However, getting an inaccurate value with high precision is not
something most numerical analysts would be happy about.
 
J

jacob navia

James said:
There are no guarantees about the accuracy for implementations that
don't pre-define __STDC_IEC_559__. The Numerical Limits section he cited
does, however, contain a great many guarantees about things other than
the accuracy.

That is fine but we are speaking about the accuracy here
...

A library can't change the way that floating point math is handled by
the compiler in your own functions.

Exactly, and this is what is happening here.
 

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

Similar Threads

Fibonacci 0
Java OpenJDK Floating Point Dare 3
Crossword 2
Crossword 14
Drawing missing in bitmap in a pure C win32 program 4
Floating point to integer casting 48
floating point 13
Java Problems (Really Need Help!) 2

Members online

No members online now.

Forum statistics

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

Latest Threads

Top