By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
429,384 Members | 714 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 429,384 IT Pros & Developers. It's quick & easy.

Compiler allowed to do this?

P: n/a
float nanometers(long pm)
{
return pm / 1000.0f;
}
void f()
{
if(nanometers(309311L) == nanometers(309311L))
{
// do something
}
}

The 'if' expression resolves to false, probably because one float value is stored and reloaded but
the other remains in the FPU in extended precision (I examined the assembler). I know you have to be
careful when comparing floats, but I'd expect the same values undergoing the same operations to end
up the _same_, and I'd like to know if the compiler is conforming to the standard.

The compiler is VS .NET 2003 in debug mode (no optimization) and with the /Op switch turned on
(improve float consistency).

DW
Sep 21 '06 #1
Share this Question
Share on Google+
19 Replies


P: n/a
David W wrote:
float nanometers(long pm)
{
return pm / 1000.0f;
}
void f()
{
if(nanometers(309311L) == nanometers(309311L))
{
// do something
}
}

The 'if' expression resolves to false, probably because one float value is
stored and reloaded but the other remains in the FPU in extended precision
(I examined the assembler). I know you have to be careful when comparing
floats, but I'd expect the same values undergoing the same operations to
end up the _same_, and I'd like to know if the compiler is conforming to
the standard.
[snip]

I think the compiler is within its rights. At least that is how I would
interpret the intention of [5/10]:

The values of the floating operands and the results of floating
expressions may be represented in greater precision and range than that
required by the type; the types are not changed thereby
Best

Kai-Uwe Bux
Sep 21 '06 #2

P: n/a
"Kai-Uwe Bux" <jk********@gmx.netwrote in message
news:ee**********@murdoch.acc.Virginia.EDU...
David W wrote:
float nanometers(long pm)
{
return pm / 1000.0f;
}
void f()
{
if(nanometers(309311L) == nanometers(309311L))
{
// do something
}
}

The 'if' expression resolves to false, probably because one float value
is
stored and reloaded but the other remains in the FPU in extended
precision
(I examined the assembler). I know you have to be careful when comparing
floats, but I'd expect the same values undergoing the same operations to
end up the _same_, and I'd like to know if the compiler is conforming to
the standard.
[snip]

I think the compiler is within its rights. At least that is how I would
interpret the intention of [5/10]:

The values of the floating operands and the results of floating
expressions may be represented in greater precision and range than that
required by the type; the types are not changed thereby
Well, that's just asking for bugs, IMO. Intuitively, most programmers would
expect the 'if' expression to be true, even those who are aware of round-off
issues with floats. The original code from which I created the example
worked on an earlier compiler, but now it doesn't and I can't even force the
compiler to make it work. It is a large project and I don't know where else
there will be similar bugs, and it won't be easy to find out. Either the
standard or the compiler should be better than this. It is reasonable that
identical expressions with identical inputs should produce identical
results. It should not be necessary to complicate the code with some
arbitrary maximum epsilon in a case like this.

DW

Sep 21 '06 #3

P: n/a
David W wrote:
>I think the compiler is within its rights. At least that is how I would
interpret the intention of [5/10]:

The values of the floating operands and the results of floating
expressions may be represented in greater precision and range than that
required by the type; the types are not changed thereby

Well, that's just asking for bugs, IMO. Intuitively, most programmers
would expect the 'if' expression to be true, even those who are aware of
round-off issues with floats. The original code from which I created the
example worked on an earlier compiler, but now it doesn't and I can't even
force the compiler to make it work.
What you need is a directive to prevent that the compiler holds the values
in registers, where they have another precision as if hold in memory. I do
not know, if this is a general solution (I'm using gcc), but I declare such
variables that should not be hold in registers as volatile, which tells the
compiler that the value can change unexpected from external events not
under his control. This prevents certain optimization, especially holding
the value in a register.

Regards
Stephan
Sep 21 '06 #4

P: n/a

"Stephan Kuhagen" <no****@domain.tldwrote in message
news:ee**********@kohl.informatik.uni-bremen.de...
David W wrote:
>>I think the compiler is within its rights. At least that is how I would
interpret the intention of [5/10]:

The values of the floating operands and the results of floating
expressions may be represented in greater precision and range than
that
required by the type; the types are not changed thereby

Well, that's just asking for bugs, IMO. Intuitively, most programmers
would expect the 'if' expression to be true, even those who are aware of
round-off issues with floats. The original code from which I created the
example worked on an earlier compiler, but now it doesn't and I can't
even
force the compiler to make it work.

What you need is a directive to prevent that the compiler holds the values
in registers, where they have another precision as if hold in memory. I do
not know, if this is a general solution (I'm using gcc), but I declare
such
variables that should not be hold in registers as volatile, which tells
the
compiler that the value can change unexpected from external events not
under his control. This prevents certain optimization, especially holding
the value in a register.
How about just assigning the results to variables, and later comparing those
variables? Then the values should be equal. (Right?)

-Howard

Sep 21 '06 #5

P: n/a
"Stephan Kuhagen" <no****@domain.tldwrote in message
news:ee**********@kohl.informatik.uni-bremen.de...
David W wrote:
Well, that's just asking for bugs, IMO. Intuitively, most programmers
would expect the 'if' expression to be true, even those who are aware of
round-off issues with floats. The original code from which I created the
example worked on an earlier compiler, but now it doesn't and I can't
even
force the compiler to make it work.

What you need is a directive to prevent that the compiler holds the values
in registers, where they have another precision as if hold in memory. I do
not know, if this is a general solution (I'm using gcc), but I declare
such
variables that should not be hold in registers as volatile, which tells
the
compiler that the value can change unexpected from external events not
under his control. This prevents certain optimization, especially holding
the value in a register.
Yes, the compiler should certainly offer this, but I suspect that it
doesn't. It seems wrong to me that I'm not getting what I asked for. The
function return type is specified is float, not double, but I'm getting a
float for one call and a double for the other. If the compiler did what I
asked and produced a float in both cases, at least when an equality is used,
there wouldn't be a problem. This is the worst kind of inconsistency and is
taking the latitude the standard allows too far.

DW

Sep 21 '06 #6

P: n/a
"Howard" <al*****@hotmail.comwrote in message
news:0c*******************@bgtnsc05-news.ops.worldnet.att.net...
>
How about just assigning the results to variables, and later comparing
those
variables? Then the values should be equal. (Right?)
Right, but that doesn't solve my problem of how to determine where else this
bug is occurring in a large project that used to not have it.

DW

Sep 21 '06 #7

P: n/a

"David W" <no@email.providedwrote in message
news:45******@news.eftel.com...
"Howard" <al*****@hotmail.comwrote in message
news:0c*******************@bgtnsc05-news.ops.worldnet.att.net...
>>
How about just assigning the results to variables, and later comparing
those
>variables? Then the values should be equal. (Right?)

Right, but that doesn't solve my problem of how to determine where else
this
bug is occurring in a large project that used to not have it.
Well, the project did have a problem already, and that was that it was
relying on behavior which is not guaranteed.

As for where else you have this problem, there's no way anyone here can tell
you. You'll just have to look at your own code, large or not. I don't know
of any way around it, sorry.

But it seems odd to me that you're comparing the results of two identical
function calls in the first place. I'm guessing this was just a made-up
test to try to replicate a real-life situation you have? If that's the
case, then you probably shouldn't be relying on two real values comparing as
exactly equal in the first place.

If you got those values from the exact same code (as in your example), then
you already know they're equal, and shouldn't need to compare. If you
obtained two values from different methods, but whose values (on paper)
should compare as equal, then you just need to know that they may not always
compare as equal.

It's often better to avoid comparisons of real numbers for exact equality,
except in specific cases, such as where they both hold integral values of
small enough magnitude. Instead, select an error value that's sufficiently
small for your purposes, and compare for equality within plus or minus that
error value. (Or, you might be able to use some other method for making
decisions which doesn't rely on the values at all.)

-Howard
Sep 21 '06 #8

P: n/a
"Howard" <al*****@hotmail.comwrote in message
news:i2*******************@bgtnsc05-news.ops.worldnet.att.net...
>
"David W" <no@email.providedwrote in message
news:45******@news.eftel.com...
"Howard" <al*****@hotmail.comwrote in message
news:0c*******************@bgtnsc05-news.ops.worldnet.att.net...
>
How about just assigning the results to variables, and later comparing
those
variables? Then the values should be equal. (Right?)
Right, but that doesn't solve my problem of how to determine where else
this
bug is occurring in a large project that used to not have it.

Well, the project did have a problem already, and that was that it was
relying on behavior which is not guaranteed.
Yes, but it's an understandable problem. I don't imagine there are many programmers who would
instinctively think it's a risky thing to do. In how many programming languages would this not work?
As for where else you have this problem, there's no way anyone here can tell
you. You'll just have to look at your own code, large or not. I don't know
of any way around it, sorry.
I wasn't asking for help on that. I was only pointing out the trouble that this unreasonable
compiler behaviour has caused.
But it seems odd to me that you're comparing the results of two identical
function calls in the first place. I'm guessing this was just a made-up
test to try to replicate a real-life situation you have?
Of course.
If that's the
case, then you probably shouldn't be relying on two real values comparing as
exactly equal in the first place.
Why? I have the same starting values - two identical longs - and they are undergoing exactly the
same operations. Naturally they should be produce the same result, even in floats.
If you got those values from the exact same code (as in your example), then
you already know they're equal, and shouldn't need to compare.
I don't know they are equal in the real program, where the longs are variables, not compile-time
constants.
If you
obtained two values from different methods, but whose values (on paper)
should compare as equal, then you just need to know that they may not always
compare as equal.

It's often better to avoid comparisons of real numbers for exact equality,
except in specific cases, such as where they both hold integral values of
small enough magnitude.
Or if you have identical starting values and you do identical things to them.
Instead, select an error value that's sufficiently
small for your purposes, and compare for equality within plus or minus that
error value.
Shouldn't have to do that in this case. The float values of the two results are the _same_. The
problem is that the compiler is not comparing a float with a float, even though that's what the code
says to do.

DW
Sep 21 '06 #9

P: n/a
David W wrote:
>
Yes, the compiler should certainly offer this, but I suspect that it
doesn't. It seems wrong to me that I'm not getting what I asked for. The
function return type is specified is float, not double, but I'm getting a
float for one call and a double for the other. If the compiler did what I
asked and produced a float in both cases, at least when an equality is used,
there wouldn't be a problem. This is the worst kind of inconsistency and is
taking the latitude the standard allows too far.
OT, since it's compiler specific, but look at the /fp option.
Sep 22 '06 #10

P: n/a
"red floyd" <no*****@here.dudewrote in message
news:Vs****************@newssvr14.news.prodigy.com ...
David W wrote:

Yes, the compiler should certainly offer this, but I suspect that it
doesn't. It seems wrong to me that I'm not getting what I asked for. The
function return type is specified is float, not double, but I'm getting a
float for one call and a double for the other. If the compiler did what I
asked and produced a float in both cases, at least when an equality is used,
there wouldn't be a problem. This is the worst kind of inconsistency and is
taking the latitude the standard allows too far.

OT, since it's compiler specific, but look at the /fp option.
Thanks, but there isn't a /fp option with VS .NET 2003 (i.e., MS C++ ver. 13). There's a /Fp, but
that's to do with pre-compiled headers.

DW
Sep 22 '06 #11

P: n/a
David W wrote:
"Howard" <al*****@hotmail.comwrote:

How about just assigning the results to variables, and later comparing
those variables? Then the values should be equal. (Right?)

Right, but that doesn't solve my problem of how to determine where else this
bug is occurring in a large project that used to not have it.
Grep for "=="

Sep 22 '06 #12

P: n/a
"Old Wolf" <ol*****@inspire.net.nzwrote in message
news:11**********************@i3g2000cwc.googlegro ups.com...
David W wrote:
Right, but that doesn't solve my problem of how to determine where else this
bug is occurring in a large project that used to not have it.

Grep for "=="
I did. There are 2,568 of them in 344 files.

DW
Sep 22 '06 #13

P: n/a
David W wrote:
"Howard" <al*****@hotmail.comwrote in message
news:i2*******************@bgtnsc05-news.ops.worldnet.att.net...
>>
"David W" <no@email.providedwrote in message
news:45******@news.eftel.com...
"Howard" <al*****@hotmail.comwrote in message
news:0c*******************@bgtnsc05-news.ops.worldnet.att.net...

How about just assigning the results to variables, and later comparing
those
variables? Then the values should be equal. (Right?)
No, sorry. Just a little while ago I had to solve a colleague's problem with
that, who didn't know about the "volatile-trick". He assigned the values to
two variables and then compared them, but although they had the same value,
the comparison failed. The only way he found to solve it, was to put a
printf between the assignments and the comparison... ouch. And he is _not_
a newbie! It seems, that printf kills all your register contents on that
specific compiler, so the comparison worked...
Yes, but it's an understandable problem. I don't imagine there are many
programmers who would instinctively think it's a risky thing to do. In how
many programming languages would this not work?
It is understandable, see above anecdote. I think, many compiler languages
close to hardware would not work in the expected way. But this is how
languages close hardware and complex often work: unexpected to the
programmer who did not know the pitfalls.

The problem are not the languages, I think, but the miserable design of IEEE
floating point numbers and FPUs working with them. For example Intel FPUs
internally work with a larger resolution as when storing the numbers back
into memory (which is the reason, why the comparison fails). The problem
is, that comparing IEEE FPN is not save (there are papers about that...). C
and C++ deal with real IEEE number, so they have the same problem. Other
"higher level" languages do not use them, only in their own (mostly) C
code, but not at the level, where the programmer deals with number. For
example Python or Tcl are written in C themselves so the problem exists on
the C-level. But when the programmer uses numbers in Python, he does not
deal with IEEE FPN, but instead with the higher level abstraction of those
in Python. The benefit is that he has no such annoying problems, but the
drawback is the loss in performance. You would not write a number crunching
program in Tcl, would you...?
>you. You'll just have to look at your own code, large or not. I don't
know of any way around it, sorry.

I wasn't asking for help on that. I was only pointing out the trouble that
this unreasonable compiler behaviour has caused.
Well, but it _is_ reasonable, because the program uses IEEE FPN. If it uses
a math library like gmp, you have an implementation of FPN which is
designed for speed AND safety. It's not the language or the compiler which
is bad (I never thought, I would say this about a MS Compiler... ;-), the
things, the program uses are.
>But it seems odd to me that you're comparing the results of two identical
function calls in the first place. I'm guessing this was just a made-up
test to try to replicate a real-life situation you have?

Of course.
And a good one. A programmer who doesn't know the trick, must think this was
a joke ;-)
>If you got those values from the exact same code (as in your example),
then you already know they're equal, and shouldn't need to compare.

I don't know they are equal in the real program, where the longs are
variables, not compile-time constants.
On gcc there is this option:

`-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.

This option prevents undesirable excess precision on machines such
as the 68000 where the floating registers (of the 68881) keep more
precision than a `double' is supposed to have. Similarly for the
x86 architecture. For most programs, the excess precision does
only good, but 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.

I'm sure, your compiler has a similar option, which solves the problem
globally, so you do not need to find all places, where the problem might
occur. But it makes the executable a little bit slower...

Regards
Stephan

Sep 22 '06 #14

P: n/a
David W wrote:
"Old Wolf" <ol*****@inspire.net.nzwrote in message
news:11**********************@i3g2000cwc.googlegro ups.com...
>David W wrote:
Right, but that doesn't solve my problem of how to determine where else
this bug is occurring in a large project that used to not have it.

Grep for "=="

I did. There are 2,568 of them in 344 files.
Peanuts... a good sed replace expression should do the work... ;-)

Regards
Stephan
Sep 22 '06 #15

P: n/a
"Stephan Kuhagen" <no****@domain.tldwrote in message
news:ee**********@kohl.informatik.uni-bremen.de...
David W wrote:
"Howard" <al*****@hotmail.comwrote in message
news:i2*******************@bgtnsc05-news.ops.worldnet.att.net...
>
"David W" <no@email.providedwrote in message
news:45******@news.eftel.com...
"Howard" <al*****@hotmail.comwrote in message
news:0c*******************@bgtnsc05-news.ops.worldnet.att.net...

How about just assigning the results to variables, and later comparing
those
variables? Then the values should be equal. (Right?)

No, sorry. Just a little while ago I had to solve a colleague's problem with
that, who didn't know about the "volatile-trick". He assigned the values to
two variables and then compared them, but although they had the same value,
the comparison failed. The only way he found to solve it, was to put a
printf between the assignments and the comparison... ouch. And he is _not_
a newbie! It seems, that printf kills all your register contents on that
specific compiler, so the comparison worked...
Yes, the compiler probably just optimizes out the store/load. I think /Op in my compiler is the
printf-eliminating switch for this problem :-) (i.e., store/load of floats really means that).
Yes, but it's an understandable problem. I don't imagine there are many
programmers who would instinctively think it's a risky thing to do. In how
many programming languages would this not work?

It is understandable, see above anecdote. I think, many compiler languages
close to hardware would not work in the expected way. But this is how
languages close hardware and complex often work: unexpected to the
programmer who did not know the pitfalls.

The problem are not the languages, I think, but the miserable design of IEEE
floating point numbers and FPUs working with them. For example Intel FPUs
internally work with a larger resolution as when storing the numbers back
into memory (which is the reason, why the comparison fails). The problem
is, that comparing IEEE FPN is not save (there are papers about that...). C
and C++ deal with real IEEE number, so they have the same problem. Other
"higher level" languages do not use them, only in their own (mostly) C
code, but not at the level, where the programmer deals with number. For
example Python or Tcl are written in C themselves so the problem exists on
the C-level. But when the programmer uses numbers in Python, he does not
deal with IEEE FPN, but instead with the higher level abstraction of those
in Python. The benefit is that he has no such annoying problems, but the
drawback is the loss in performance. You would not write a number crunching
program in Tcl, would you...?
I guess not.
you. You'll just have to look at your own code, large or not. I don't
know of any way around it, sorry.
I wasn't asking for help on that. I was only pointing out the trouble that
this unreasonable compiler behaviour has caused.

Well, but it _is_ reasonable,
I don't agree. I specifically asked for a comparison of two floats and it gave me a comparison of a
float and a double, and what's worse is that two calls of the same function produced that
inconsistency.
because the program uses IEEE FPN. If it uses
a math library like gmp, you have an implementation of FPN which is
designed for speed AND safety. It's not the language or the compiler which
is bad (I never thought, I would say this about a MS Compiler... ;-), the
things, the program uses are.
But it seems odd to me that you're comparing the results of two identical
function calls in the first place. I'm guessing this was just a made-up
test to try to replicate a real-life situation you have?
Of course.

And a good one. A programmer who doesn't know the trick, must think this was
a joke ;-)
If you got those values from the exact same code (as in your example),
then you already know they're equal, and shouldn't need to compare.
I don't know they are equal in the real program, where the longs are
variables, not compile-time constants.

On gcc there is this option:

`-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.

This option prevents undesirable excess precision on machines such
as the 68000 where the floating registers (of the 68881) keep more
precision than a `double' is supposed to have. Similarly for the
x86 architecture. For most programs, the excess precision does
only good, but 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.

I'm sure, your compiler has a similar option, which solves the problem
globally, so you do not need to find all places, where the problem might
occur. But it makes the executable a little bit slower...
Well, I haven't found it. If it had one I'd retract all my complaints.

DW
Sep 22 '06 #16

P: n/a

David W wrote:
"Kai-Uwe Bux" <jk********@gmx.netwrote in message
news:ee**********@murdoch.acc.Virginia.EDU...
David W wrote:
float nanometers(long pm)
{
return pm / 1000.0f;
}
void f()
{
if(nanometers(309311L) == nanometers(309311L))
{
// do something
}
}
>
The 'if' expression resolves to false, probably because one float value
is
stored and reloaded but the other remains in the FPU in extended
precision
(I examined the assembler). I know you have to be careful when comparing
floats, but I'd expect the same values undergoing the same operations to
end up the _same_, and I'd like to know if the compiler is conforming to
the standard.
[snip]

I think the compiler is within its rights. At least that is how I would
interpret the intention of [5/10]:

The values of the floating operands and the results of floating
expressions may be represented in greater precision and range than that
required by the type; the types are not changed thereby

Well, that's just asking for bugs, IMO. Intuitively, most programmers would
expect the 'if' expression to be true, even those who are aware of round-off
issues with floats. The original code from which I created the example
worked on an earlier compiler, but now it doesn't and I can't even force the
compiler to make it work.
What abourt VC's /Op switch to "improve float consistency"? The
description begins:

"This option improves the consistency of floating-point tests for
equality and inequality by disabling optimizations that could change
the precision of floating-point calculations."

In general, about the only benefit of using a float over a double is to
save a few bytes - possibly. But otherwise, most FPUs perform all
calculations with doubles anyway, making a double at least as fast (or
faster) than a float, and much more precise as well.

Greg

Sep 22 '06 #17

P: n/a
"Greg" <gr****@pacbell.netwrote in message
news:11*********************@m73g2000cwd.googlegro ups.com...
>
What abourt VC's /Op switch to "improve float consistency"? The
description begins:

"This option improves the consistency of floating-point tests for
equality and inequality by disabling optimizations that could change
the precision of floating-point calculations."
Yes, as I said in my OP, I used that switch, but to no avail. IIRC, the
description I read is not what you've quoted. I think I read only that
storing/loading variables won't be optimized. I don't recall anything about
equality/inequality. If only what you've quoted were how it works.
In general, about the only benefit of using a float over a double is to
save a few bytes - possibly. But otherwise, most FPUs perform all
calculations with doubles anyway, making a double at least as fast (or
faster) than a float, and much more precise as well.
I did a benchmark recently to test float/double speed (the subject came up
in alt.comp.lang.learn.c-c++ a week or two ago, with exactly the same claim
made). The program solves quadratic roots for pseudo-random a, b & c and
does it about 13% faster with floats. The reason might only have been
differences in RAM accesses (4 bytes v. 8) in passing values around, but
there's plenty of that in real applications. Also, it's very rare that float
precision is not sufficient for my purposes (and I am aware of the potential
effects of round-off).

Anyway, whatever disadvantages there are with floats, my equality problem
shouldn't be one of them (or shouldn't _have_ to be one of them, depending
on compiler switches). When the compiler sees an equality it should know the
importance of consistent treatment of the two operands. It could have
converted the FPU value to float first, or it could have made its temporary
local a double if it knew the other value was to remain a double (why
respect the specified float type for a local copy in one case and then
disregard it in the other?). Yet, it chooses the only method that _can't_
work for any value that won't fit precisely in a float.

DW

Sep 22 '06 #18

P: n/a
In article <QQ*******************@nasal.pacific.net.au>,
no@email.provided says...
"Old Wolf" <ol*****@inspire.net.nzwrote in message
news:11**********************@i3g2000cwc.googlegro ups.com...
David W wrote:
Right, but that doesn't solve my problem of how to determine where else this
bug is occurring in a large project that used to not have it.
Grep for "=="

I did. There are 2,568 of them in 344 files.
The following is NOT something I'd normally recommend, but under the
circumstances, it may be the least of the available evils:

// myfloat.h (or whatever name you prefer).
//
// Warning: tested to some degree, but almost certainly not
// thoroughly. I've plugged it into a number of programs that
// use floating point, but made no serious attempt at ensuring
// full test coverage.
#include <iostream>

template <class T>
class my_float {
T f_;
public:
#define m_f my_float
m_f(T f=(T)0) : f_(f) {}

template <class U>
m_f(U const &f) : f_((T)f) {}

bool operator==(m_f const &c) const {
volatile T t1 = f_, t2=c.f_;
return t1 == t2;
}

bool operator!=(m_f const &c) const {
volatile T t1 = f_, t2=c.f_;
return t1 != t2;
}

bool operator<(m_f const &c) const {
volatile T t1(f_), t2(c.f_);
return t1 < t2;
}

bool operator>(m_f const &c) const {
volatile T t1(f_), t2(c.f_);
return t1 t2;
}

bool operator<=(m_f const &c) const {
volatile T t1(f_), t2(c.f_);
return t1<=t2;
}

bool operator>=(m_f const &c) const {
volatile T t1(f_), t2(c.f_);
return t1 >= t2;
}

long to_long() { return long(f_); }
int to_int() { return int(f_); }
unsigned long to_ulong() { return unsigned long(f_); }
unsigned int to_uint() { return unsigned int(f_); }

m_f &operator +=(m_f const &m) { f_ += m.f_; return *this; }
m_f &operator -=(m_f const &m) { f_ -= m.f_; return *this; }
m_f &operator *=(m_f const &m) { f_ *= m.f_; return *this; }
m_f &operator /=(m_f const &m) { f_ /= m.f_; return *this; }

friend m_f
operator+(m_f const &a, m_f const &b) { return m_f(a.f_+b.f_); }

friend m_f
operator-(m_f const &a, m_f const &b) { return m_f(a.f_-b.f_); }

friend m_f
operator*(m_f const &a, m_f const &b) { return m_f(a.f_*b.f_); }

friend m_f
operator/(m_f const &a, m_f const &b) { return m_f(a.f_/b.f_); }

friend std::ostream &operator<<(std::ostream &os, m_f const &c) {
return os << c.f_;
}

friend std::istream &operator>>(std::istream &is, m_f &c) {
return is >c.f_;
}
#undef m_f
};

#define float my_float<float>
#define double my_float<double>

Put this it into a header file, then include that header into your
source files. There's a reasonable chance you can make things work
reasonably easily -- the main change your code may require would happen
because this class requires conversions to integer types to be explicit,
using something like whatever.to_int() instead of a type cast operator.

Another possibility would be to make every comparison operator assert
(false) or something on that order. This should give you a much better
handle on the real problem, ignoring things like comparisons of integer
types that you don't care about. After fixing all of the floating point
comparisons, you'd simply quit using the header, and your code would be
back to normal.

Code like this that re-defines the underlying language tends to be
fragile, and this is not likely to be an exception -- thus the
suggestion for just using it temporarily. Nonetheless, there's a pretty
fair chance something on this order will help you find and fix the real
problems while more or less automatically ignoring comparisons of
integer types and such that you don't care about.

--
Later,
Jerry.

The universe is a figment of its own imagination.
Sep 23 '06 #19

P: n/a
"Jerry Coffin" <jc*****@taeus.comwrote in message
news:MP************************@news.sunsite.dk...
In article <QQ*******************@nasal.pacific.net.au>,
no@email.provided says...

The following is NOT something I'd normally recommend, but under the
circumstances, it may be the least of the available evils:

// myfloat.h (or whatever name you prefer).
//
// Warning: tested to some degree, but almost certainly not
// thoroughly. I've plugged it into a number of programs that
// use floating point, but made no serious attempt at ensuring
// full test coverage.
#include <iostream>

template <class T>
class my_float {
T f_;
public:
#define m_f my_float
m_f(T f=(T)0) : f_(f) {}

template <class U>
m_f(U const &f) : f_((T)f) {}

bool operator==(m_f const &c) const {
volatile T t1 = f_, t2=c.f_;
return t1 == t2;
}

bool operator!=(m_f const &c) const {
volatile T t1 = f_, t2=c.f_;
return t1 != t2;
}

bool operator<(m_f const &c) const {
volatile T t1(f_), t2(c.f_);
return t1 < t2;
}

bool operator>(m_f const &c) const {
volatile T t1(f_), t2(c.f_);
return t1 t2;
}

bool operator<=(m_f const &c) const {
volatile T t1(f_), t2(c.f_);
return t1<=t2;
}

bool operator>=(m_f const &c) const {
volatile T t1(f_), t2(c.f_);
return t1 >= t2;
}

long to_long() { return long(f_); }
int to_int() { return int(f_); }
unsigned long to_ulong() { return unsigned long(f_); }
unsigned int to_uint() { return unsigned int(f_); }

m_f &operator +=(m_f const &m) { f_ += m.f_; return *this; }
m_f &operator -=(m_f const &m) { f_ -= m.f_; return *this; }
m_f &operator *=(m_f const &m) { f_ *= m.f_; return *this; }
m_f &operator /=(m_f const &m) { f_ /= m.f_; return *this; }

friend m_f
operator+(m_f const &a, m_f const &b) { return m_f(a.f_+b.f_); }

friend m_f
operator-(m_f const &a, m_f const &b) { return m_f(a.f_-b.f_); }

friend m_f
operator*(m_f const &a, m_f const &b) { return m_f(a.f_*b.f_); }

friend m_f
operator/(m_f const &a, m_f const &b) { return m_f(a.f_/b.f_); }

friend std::ostream &operator<<(std::ostream &os, m_f const &c) {
return os << c.f_;
}

friend std::istream &operator>>(std::istream &is, m_f &c) {
return is >c.f_;
}
#undef m_f
};

#define float my_float<float>
#define double my_float<double>

Put this it into a header file, then include that header into your
source files.
Should be straightforward, since we have one or two headers that are already
included everywhere.
There's a reasonable chance you can make things work
reasonably easily -- the main change your code may require would happen
because this class requires conversions to integer types to be explicit,
using something like whatever.to_int() instead of a type cast operator.

Another possibility would be to make every comparison operator assert
(false) or something on that order. This should give you a much better
handle on the real problem, ignoring things like comparisons of integer
types that you don't care about. After fixing all of the floating point
comparisons, you'd simply quit using the header, and your code would be
back to normal.

Code like this that re-defines the underlying language tends to be
fragile, and this is not likely to be an exception -- thus the
suggestion for just using it temporarily. Nonetheless, there's a pretty
fair chance something on this order will help you find and fix the real
problems while more or less automatically ignoring comparisons of
integer types and such that you don't care about.
Great idea! I'll give it a try. Thanks for taking the time.

DW

Sep 24 '06 #20

This discussion thread is closed

Replies have been disabled for this discussion.