Discussion:
bug compilateur borland
(too old to reply)
Christian PANEL
2008-05-16 23:20:24 UTC
Permalink
le code suivant

#include <stdio.h>
#include <conio.h>
#include <math.h>

int main()
{
double d1 = 4.5868578588821;
double d2 = 4.5868578588820;
float f1 = d1;
float f2 = d2;
puts("d1 != d2");
puts(d1!=d2 ? "OUI" : "NON");
puts("f1 != f2");
puts(f1!=f2 ? "OUI" : "NON");
puts("float(d1) != float(d2)");
puts(float(d1)!=float(d2) ? "OUI" : "NON");
getch();

provoque la sortie
OUI NON OUI sur TOUS les compilateurs borland y compris Builder2007
et
OUI NON NON sur les compilateur MSC et GNU (ce qui est là normal)
Thomas Maeder [TeamB]
2008-05-17 06:15:12 UTC
Permalink
Bonjour

Puisque la vaste majorité des participants de ce groupe est de langue
anglaise, il vaut mieux écrire dans cette langue.
Post by Christian PANEL
le code suivant
#include <stdio.h>
#include <conio.h>
#include <math.h>
int main()
{
double d1 = 4.5868578588821;
double d2 = 4.5868578588820;
float f1 = d1;
float f2 = d2;
puts("d1 != d2");
puts(d1!=d2 ? "OUI" : "NON");
puts("f1 != f2");
puts(f1!=f2 ? "OUI" : "NON");
puts("float(d1) != float(d2)");
puts(float(d1)!=float(d2) ? "OUI" : "NON");
getch();
provoque la sortie
OUI NON OUI sur TOUS les compilateurs borland y compris Builder2007
et
OUI NON NON sur les compilateur MSC et GNU (ce qui est là normal)
[Transl.: the code produces "OUI NON OUI" if compiled with Borland
compilers, and "OUI NON NON" (which is to be expected) if compiled
with Microsoft or Gnu compilers.]

Non-integral numbers are typically represented approximatively (using
floating point objects) by computers, because representing them
exactly would require infinite memory. Comparing floating point
numbers for (in)equality can therefore lead to surprising rcsults
unless one does a very careful analysis of the calculations and how
they are executed by a particular C++ implementation.

In practice, it often helps to consider two floating point numbers to
be "equal" if their difference is below some small value.
Christian PANEL
2008-05-17 08:26:30 UTC
Permalink
Post by Thomas Maeder [TeamB]
Bonjour
Puisque la vaste majorité des participants de ce groupe est de langue
anglaise, il vaut mieux écrire dans cette langue.
Post by Christian PANEL
le code suivant
#include <stdio.h>
#include <conio.h>
#include <math.h>
int main()
{
double d1 = 4.5868578588821;
double d2 = 4.5868578588820;
float f1 = d1;
float f2 = d2;
puts("d1 != d2");
puts(d1!=d2 ? "OUI" : "NON");
puts("f1 != f2");
puts(f1!=f2 ? "OUI" : "NON");
puts("float(d1) != float(d2)");
puts(float(d1)!=float(d2) ? "OUI" : "NON");
getch();
provoque la sortie
OUI NON OUI sur TOUS les compilateurs borland y compris Builder2007
et
OUI NON NON sur les compilateur MSC et GNU (ce qui est là normal)
[Transl.: the code produces "OUI NON OUI" if compiled with Borland
compilers, and "OUI NON NON" (which is to be expected) if compiled
with Microsoft or Gnu compilers.]
Non-integral numbers are typically represented approximatively (using
floating point objects) by computers, because representing them
exactly would require infinite memory. Comparing floating point
numbers for (in)equality can therefore lead to surprising rcsults
unless one does a very careful analysis of the calculations and how
they are executed by a particular C++ implementation.
In practice, it often helps to consider two floating point numbers to
be "equal" if their difference is below some small value.
Sorry, I also use french forum and I mistake...

You're telling me! If you look at seriously the code, you could see there is
REALLY a problem...
But you can ignore it...
Programmers... not!
Alan Bellingham
2008-05-17 09:29:58 UTC
Permalink
Post by Christian PANEL
You're telling me! If you look at seriously the code, you could see there is
REALLY a problem...
But you can ignore it...
Programmers... not!
So you're complaining that

double d1 = 4.5868578588821;
double d2 = 4.5868578588820;
puts("float(d1) != float(d2)");
puts(float(d1)!=float(d2) ? "OUI" : "NON");

produces different results on different compilers?

Let's look at what's going on:

double d1 = 4.5868578588821;
double d2 = 4.5868578588820;

Two doubles, that differ only by a very tiny amount (parts per
trillion).

float f1 = d1;
float f2 = d2;

Assignment to a pair of floats, *which are then stored*! This causes
truncation and/or rounding.

puts("d1 != d2");
puts(d1!=d2 ? "OUI" : "NON");

Comparing the original doubles. Which are (as one expects) unequal.

puts("f1 != f2");
puts(f1!=f2 ? "OUI" : "NON");

Comparing the stored floats which are, due to truncation, equal.

puts("float(d1) != float(d2)");
puts(float(d1)!=float(d2) ? "OUI" : "NON");

Comparing two *in-memory* casts of the doubles. You expect the result to
be the same as comparing the stored float values. And they're not.

Welcome to floating point. What's in memory may be slightly higher
precision that what actually gets stored when you save it.

You may be able to control whether you see this effect or not by using
the _control87() function. If I recall correctly, (and I may be wrong)
Microsoft and Borland code tend to have different default settings for
it.

The problem is that you do not understand floating point as done with
computers, or you wouldn't be so surprised. As an additional problem,
your original numbers that you wrote down aren't exactly representable
in binary, so you're manipulating a pair of recurring binary fractions
to start with.

The best paper I know on the subject (and I'm not an expert) is this
one: http://docs.sun.com/source/806-3568/ncg_goldberg.html - or "What
Every Computer Scientist Should Know About Floating-Point Arithmetic".
It dates back to 1991, but too few people have heard of it.

Alan Bellingham
--
Team Browns
ACCU Conference 2009: to be announced
Christian PANEL
2008-05-17 11:32:34 UTC
Permalink
you want that I believe that the moon is made of green cheese ?

I know what is happen when a floating number is loaded in the FPU
and I find that when I compare two float numbers that are the same the
compiler say they are equal

readers will appreciate :

double d1 = 4.5868578588821;
double d2 = 4.5868578588820;
float f1 = d1;
float f2 = d2;

In Others compilers :

d1==d2 give same result than float(d1)==float(d2)

In Borland compilers

it didn't
Post by Alan Bellingham
Post by Christian PANEL
You're telling me! If you look at seriously the code, you could see there is
REALLY a problem...
But you can ignore it...
Programmers... not!
So you're complaining that
double d1 = 4.5868578588821;
double d2 = 4.5868578588820;
puts("float(d1) != float(d2)");
puts(float(d1)!=float(d2) ? "OUI" : "NON");
produces different results on different compilers?
double d1 = 4.5868578588821;
double d2 = 4.5868578588820;
Two doubles, that differ only by a very tiny amount (parts per
trillion).
float f1 = d1;
float f2 = d2;
Assignment to a pair of floats, *which are then stored*! This causes
truncation and/or rounding.
puts("d1 != d2");
puts(d1!=d2 ? "OUI" : "NON");
Comparing the original doubles. Which are (as one expects) unequal.
puts("f1 != f2");
puts(f1!=f2 ? "OUI" : "NON");
Comparing the stored floats which are, due to truncation, equal.
puts("float(d1) != float(d2)");
puts(float(d1)!=float(d2) ? "OUI" : "NON");
Comparing two *in-memory* casts of the doubles. You expect the result to
be the same as comparing the stored float values. And they're not.
Welcome to floating point. What's in memory may be slightly higher
precision that what actually gets stored when you save it.
You may be able to control whether you see this effect or not by using
the _control87() function. If I recall correctly, (and I may be wrong)
Microsoft and Borland code tend to have different default settings for
it.
The problem is that you do not understand floating point as done with
computers, or you wouldn't be so surprised. As an additional problem,
your original numbers that you wrote down aren't exactly representable
in binary, so you're manipulating a pair of recurring binary fractions
to start with.
The best paper I know on the subject (and I'm not an expert) is this
one: http://docs.sun.com/source/806-3568/ncg_goldberg.html - or "What
Every Computer Scientist Should Know About Floating-Point Arithmetic".
It dates back to 1991, but too few people have heard of it.
Alan Bellingham
--
Team Browns
ACCU Conference 2009: to be announced
Alan Bellingham
2008-05-17 15:59:35 UTC
Permalink
Post by Christian PANEL
you want that I believe that the moon is made of green cheese ?
Oddly enough, I find that compiling the example with the Microsoft
compiler produces an executable that outputs exactly what you see with
the Borland compiler. I've tried persuading the two compilers (BCB5 and
VC++6) to produce differences, with no luck. The only difference I can
produce is in the result of calling _control87(0, 0).

Alan Bellingham
--
Team Browns
ACCU Conference 2009: to be announced
Vladimir Grigoriev
2008-05-19 11:31:49 UTC
Permalink
Post by Alan Bellingham
Oddly enough, I find that compiling the example with the Microsoft
compiler produces an executable that outputs exactly what you see with
the Borland compiler. I've tried persuading the two compilers (BCB5 and
VC++6) to produce differences, with no luck. The only difference I can
produce is in the result of calling _control87(0, 0).
I testes with Visual C++ 2005 EE and got the following results

double d1 = 4.5868578588821;

double d2 = 4.5868578588820;

float f1 = d1;

float f2 = d2;

if ( d1 == d2 )

std::cout << "Doubles are equal." << std::endl;

else

std::cout << "Doubles are NOT equal." << std::endl;

if ( f1 == f2 )

std::cout << "Floats are equal." << std::endl;

else

std::cout << "Floats are NOT equal." << std::endl;

if ( (float )d1 == (float)d2 )

std::cout << "Floats are equal." << std::endl;

else

std::cout << "Floats are NOT equal." << std::endl;



Doubles are NOT equal.
Floats are equal.
Floats are equal.



Vladimir Grigoriev
Christian PANEL
2008-05-17 13:15:25 UTC
Permalink
you want that I believe that the moon is made of green cheese ?

I know what is happen when a floating number is loaded in the FPU
and I find that when I compare two float numbers that are the same the
compiler say they are equal

readers will appreciate :

double d1 = 4.5868578588821;
double d2 = 4.5868578588820;
float f1 = d1;
float f2 = d2;

In Others compilers :

f1==f2 give same result than float(d1)==float(d2)

In Borland compilers

it didn't
Post by Alan Bellingham
Post by Christian PANEL
You're telling me! If you look at seriously the code, you could see there is
REALLY a problem...
But you can ignore it...
Programmers... not!
So you're complaining that
double d1 = 4.5868578588821;
double d2 = 4.5868578588820;
puts("float(d1) != float(d2)");
puts(float(d1)!=float(d2) ? "OUI" : "NON");
produces different results on different compilers?
double d1 = 4.5868578588821;
double d2 = 4.5868578588820;
Two doubles, that differ only by a very tiny amount (parts per
trillion).
float f1 = d1;
float f2 = d2;
Assignment to a pair of floats, *which are then stored*! This causes
truncation and/or rounding.
puts("d1 != d2");
puts(d1!=d2 ? "OUI" : "NON");
Comparing the original doubles. Which are (as one expects) unequal.
puts("f1 != f2");
puts(f1!=f2 ? "OUI" : "NON");
Comparing the stored floats which are, due to truncation, equal.
puts("float(d1) != float(d2)");
puts(float(d1)!=float(d2) ? "OUI" : "NON");
Comparing two *in-memory* casts of the doubles. You expect the result to
be the same as comparing the stored float values. And they're not.
Welcome to floating point. What's in memory may be slightly higher
precision that what actually gets stored when you save it.
You may be able to control whether you see this effect or not by using
the _control87() function. If I recall correctly, (and I may be wrong)
Microsoft and Borland code tend to have different default settings for
it.
The problem is that you do not understand floating point as done with
computers, or you wouldn't be so surprised. As an additional problem,
your original numbers that you wrote down aren't exactly representable
in binary, so you're manipulating a pair of recurring binary fractions
to start with.
The best paper I know on the subject (and I'm not an expert) is this
one: http://docs.sun.com/source/806-3568/ncg_goldberg.html - or "What
Every Computer Scientist Should Know About Floating-Point Arithmetic".
It dates back to 1991, but too few people have heard of it.
Alan Bellingham
--
Team Browns
ACCU Conference 2009: to be announced
Old Wolf
2008-05-18 23:56:27 UTC
Permalink
Post by Alan Bellingham
So you're complaining that
double d1 = 4.5868578588821;
double d2 = 4.5868578588820;
puts("float(d1) != float(d2)");
puts(float(d1)!=float(d2) ? "OUI" : "NON");
produces different results on different compilers?
No, the complaint is that float(d1) is producing
a different result to: float f1 = d1;
Post by Alan Bellingham
puts("f1 != f2");
puts(f1!=f2 ? "OUI" : "NON");
Comparing the stored floats which are, due to truncation, equal.
puts("float(d1) != float(d2)");
puts(float(d1)!=float(d2) ? "OUI" : "NON");
Comparing two *in-memory* casts of the doubles. You expect the
result to be the same as comparing the stored float values. And
they're not.
To be clear, it is a compiler bug if float(d1) does not
actually convert d1 to a float. You have described the mechanism
behind the compiler's failure, but that does not excuse the bug.
The outputs of the latter two 'puts' calls must match.
Old Wolf
2008-05-18 23:59:12 UTC
Permalink
Post by Old Wolf
To be clear, it is a compiler bug if float(d1) does not
actually convert d1 to a float.
To qualify that slightly: it is a compiler bug if the compiler
is in standards-conforming mode, and float(d1) does not actually
convert d1 to a float.

It's not unknown for compilers to operate in a 'fast' floating
point mode by default, that doesn't meet the guarantees of the
C++ standard, unless you specifically invoke standard mode
with the -ansi switch or whatever.
Tom420
2008-06-29 20:12:24 UTC
Permalink
Post by Old Wolf
Post by Old Wolf
To be clear, it is a compiler bug if float(d1) does not
actually convert d1 to a float.
To qualify that slightly: it is a compiler bug if the compiler
is in standards-conforming mode, and float(d1) does not actually
convert d1 to a float.
It's not unknown for compilers to operate in a 'fast' floating
point mode by default, that doesn't meet the guarantees of the
C++ standard, unless you specifically invoke standard mode
with the -ansi switch or whatever.
The part "fast floating point" got my interest, so I tried the following:

[code]
double d1 = 4.5868578588821;
double d2 = 4.5868578588820;
float f1 = d1;
float f2 = d2;

if(d1 == d2)
Memo1->Lines->Add("Equal");
else
Memo1->Lines->Add("NOT Equal");

if(f1 == f2)
Memo1->Lines->Add("Equal");
else
Memo1->Lines->Add("NOT Equal");

if(float(d1) == float(d2))
Memo1->Lines->Add("Equal");
else
Memo1->Lines->Add("NOT Equal");

Memo1->Lines->Add(d1);
Memo1->Lines->Add(d2);
Memo1->Lines->Add((float)d1);
Memo1->Lines->Add((float)d2);
[/code]


With the Fast Floating Point option ON (from Project > Options ... > C++
Compiler > Floating Point) I got the following result:

NOT Equal
Equal
NOT Equal
4.5868578588821
4.586857858882
4.5868578588821
4.586857858882

With the Fast Floating Point option OFF I got the following:

NOT Equal
Equal
NOT Equal
4.5868578588821
4.586857858882
4.58685779571533
4.58685779571533


While you were correct that the Fast floating point option might make a
difference, I'm perplex that the result is not the same when comparing
(==) and printing the result....

That is, with fast floating point ON or OFF there is never a conversion
for (float)d1... but there is one while printing the value....

Goran Ekstrom
2008-05-18 18:23:37 UTC
Permalink
Post by Christian PANEL
You're telling me! If you look at seriously the code, you could see there
is REALLY a problem...
But you can ignore it...
Programmers... not!
OMG! Go learn some manners then someone may give a damn about your issues.
Sabetay Toros
2008-05-19 11:58:00 UTC
Permalink
Post by Goran Ekstrom
Post by Christian PANEL
You're telling me! If you look at seriously the code, you could see there
is REALLY a problem...
But you can ignore it...
Programmers... not!
OMG! Go learn some manners then someone may give a damn about your issues.
Goran,

Aha!. And also telling us he is a better programmer than the expert
Thomas Mader.

Sabetay
Goran Ekstrom
2008-05-20 18:52:01 UTC
Permalink
Aha!. And also telling us he is a better programmer than the expert Thomas
Mader.
LOL, yeah, that will surely help! OK, I may have some sympathy with the guy
if he was under great deadline pressure or something (god knows I've been
there myself a few times) but really... People never ceases to amaze me.

Goran
Loading...