From: AlMel on
Dear all!

I'm writing a fairly simple program interpreting an input with numbers
in exponential notation. I have encountered a problem in MS VisualC++
2008 Express Edition which is illustrated in the following code:

#include <iostream>
#include <string>
#include <sstream>

using namespace std;

int main() {

string s1 = "0.003 \n 0.0003 \n 0.00003 \n
0.000000000000000000000000000000000000000000000000000003";
string s2 = "3.e-3 \n 3.e-4 \n 3.e-5 \n 3.e-54";

stringstream ss1(s1), ss2(s2);

double d1, d2;

ss1 >> d1;
ss2 >> d2;
cout << d1 << " = " << "3.e-3" << " ? " << int(d1 == d2) <<
endl;

ss1 >> d1;
ss2 >> d2;
cout << d1 << " = " << "3.e-4" << " ? " << int(d1 == d2) <<
endl;

ss1 >> d1;
ss2 >> d2;
cout << d1 << " = " << "3.e-5" << " ? " << int(d1 == d2) <<
endl;

ss1 >> d1;
ss2 >> d2;
cout << d1 << " = " << "3.e-54" << " ? " << int(d1 == d2) <<
endl;

cin >> d1;

return 0;
}

The output is:

0.003 = 3.e-3 ? 1
0.0003 = 3.e-4 ? 0
3e-005 = 3.e-5 ? 0
3e-054 = 3.e-54 ? 0

If I compile the same program using Mingw (GCC 4.4.0) on the same
machine under the same Windows, I get the correct answers:

0.003 = 3.e-3 ? 1
0.0003 = 3.e-4 ? 1
3e-005 = 3.e-5 ? 1
3e-054 = 3.e-54 ? 1

I think the problem is in the standard library, which is hard to
repair, but may be I'm wrong. Any ideas on how to get the same correct
output on MS VisualC+++ 2008 Express Edition? Would be nice if someone
could test the code on pro edition or on newer VisualC++ versions.

Thank you in advance!

With best wishes,
Alex

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Lailoken on
On Jun 6, 8:13 am, AlMel <alexander.melkoze...(a)gmail.com> wrote:
> Dear all!
>
> I'm writing a fairly simple program interpreting an input with numbers
> in exponential notation. I have encountered a problem in MS VisualC++
> 2008 Express Edition which is illustrated in the following code:

Well, I think the first thing you need to read:

"What Every Computer Scientist Should Know About Floating-Point
Arithmetic"
http://docs.sun.com/source/806-3568/ncg_goldberg.html

Also, you may want to set some project settings in Visual Studio that
has to do with floating point accuracy/speed (I don't recall where/
what they are, but I know they are there... although it is unlikely
that these will solve your 'problem').

But the gist of it is that you cannot, *should not*, use '=' to
compare floating point numbers in any application where you value
correctness. Write a Equals() function to do this that takes a
optional (machine) epsilon parameter to denote variance.

This is the life of floating point programmers... live with it. If you
need fixed point decimals perhaps consider using integer math with
shifted decimals (a lot of caveats go with this one too).


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Pete Becker on
On 2010-06-06 06:18:10 -1000, Lailoken said:

> But the gist of it is that you cannot, *should not*, use '=' to
> compare floating point numbers in any application where you value
> correctness. Write a Equals() function to do this that takes a
> optional (machine) epsilon parameter to denote variance.

This is a really bad idea. The application's tolerance for roundoff
errors depends on the precision of the data that it's operating on, the
details of the computations that are being done on that data, and the
desired results. Replacing == with nearly-equal doesn't address any of
those issues. The only way to get accurate results from any computation
is to understand what it's doing and what the implications are for the
results.

Nobody would make this sort of recommendation for integer arithmetic,
despite the fact that 1/3 multiplied by 3 is 0, not 1. The reason, of
course, is that you've learned how to manage the roundoff errors that
occur with integer math. If you're serious about floating-point math
you have to do the same thing: learn how it works.

Note also that nearly-equal is not transitive, so using it will
introduce a whole new set of peculiar problems.

--
Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The
Standard C++ Library Extensions: a Tutorial and Reference
(www.petebecker.com/tr1book)

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Andrew on
On 6 June, 22:18, Lailoken <lailo...(a)gmail.com> wrote:
> On Jun 6, 8:13 am, AlMel <alexander.melkoze...(a)gmail.com> wrote:
>
> > Dear all!
>
> > I'm writing a fairly simple program interpreting an input with numbers
> > in exponential notation. I have encountered a problem in MS VisualC++
> > 2008 Express Edition which is illustrated in the following code:
>
> Well, I think the first thing you need to read:
>
> "What Every Computer Scientist Should Know About Floating-Point
> Arithmetic"http://docs.sun.com/source/806-3568/ncg_goldberg.html
>
> Also, you may want to set some project settings in Visual Studio that
> has to do with floating point accuracy/speed (I don't recall where/
> what they are, but I know they are there... although it is unlikely
> that these will solve your 'problem').
>
> But the gist of it is that you cannot, *should not*, use '=' to
> compare floating point numbers in any application where you value
> correctness. Write a Equals() function to do this that takes a
> optional (machine) epsilon parameter to denote variance.

Almost, but not quite. Knuth recommends that a relative tolerance is
used. Boost has tackled this issue, which is documented at
http://www.boost.org/doc/libs/1_32_0/libs/test/doc/components/test_tools/floating_point_comparison.html.

Also, as Pete indicates, it is very dangerous to do these sorts of
comparison in mid-calculation. I find that compare with tolerance is
ok in test harnesses for testing that a complex calculation finally
yields the result that is desired.

Regards,

Andrew Marlow

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: AlMel on
> But the gist of it is that you cannot, *should not*, use '=' to
> compare floating point numbers in any application where you value
> correctness. Write a Equals() function to do this that takes a
> optional (machine) epsilon parameter to denote variance.
>
> This is the life of floating point programmers... live with it. If you
> need fixed point decimals perhaps consider using integer math with
> shifted decimals (a lot of caveats go with this one too).

Thank you for your help. I think that I did not formulate the problem
clear enough. The problem here is not the floating-point '=' operator
but rather Visual C++ standard library (in particular, the
stringstream implimentation) which does not interpret "0.0003" and
"3.e-4" as a same floating-point number. The resulting binary floating-
point representations differ by a small quantity (epsilon). In GCC,
the standard library correctly reads both notations and produces the
same binary representation.

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]