 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Paul A Bristow Guest
|
Posted: Fri Oct 15, 2004 4:34 am Post subject: Should Float(s) to string(stream) be re-input exactly the sa |
|
|
Whilest devising tests for the Boost lexical_cast function,
I have encountered (for one compiler version) some surprising (to me)
results outputting
floats to decimal digit strings and reading them back in.
Providing you use enough decimal digits, I expected the result of
this 'loopback' to be the same, for example:
float f = any_float_value; // Similarly for other types, UDTs even?
std::stringstream s;
s.precision(float_significant_decimal_digits); // 9 decimal digits should
be enough (see Appendix below).
s << f; // Output to decimal digit string(stream).
float rf;
s >> rf; // read string back into float.
My expectation is that f == rf for ALL possible float values
(and indeed this WAS true for an exhaustive test with a previous version of
a well-known compiler,
and for a randomish sample of double and long double values).
A recent version outputs the same decimal digit strings
- BUT the value read back in is 1 least significant binary digit different -
suspiciously only for 1/3 of the float values.
(Nor does increasing the number of decimal digits output via s.precision()
change this).
But perhaps this is not a Standard expectation?
Paul Bristow
Appendix
For float, the number of significant binary digits is
int float_significand_digits =
std::numeric_limits<float>::digits; // FLT_MANT_DIG == 24
for 32-bit FP
the number of _guaranteed_ accurate decimal digits is given by
int float_guaranteed_decimal_digits =
std::numeric_limits<float>::digits10;
and is 6 for the MSVC 32-bit floating point format.
The maximum number of digits that _can_ be significant is
given by the formula
float const log10Two = 0.30102999566398119521373889472449F; // log10(2.)
int float_significant_digits = int(ceil(1 +
float_significand_digits * log10Two));
// Note that C++ compiler will NOT evaluate log10
(2.) at compile time, nor a floating point division,
// but an WILL perform an integer division, so can
use 301/1000 as an approximation.
// 3010/10000 is the nearest approximation using
short int (10000 < max of 32767)
but this is convenient numerically equivalent to
int const float_significant_decimal_digits = 2 +
std::numeric_limits
which CAN be calculated at compile time, and is 9 decimal
digits for the IEEE 32-bit floating point format.
To demonstrate, the following test asserts:
#include <iomanip>
#include <cassert>
#include <limits>
#include <sstream>
using std::setprecision;
int main()
{
int const float_significant_decimal_digits = 2 +
std::numeric_limits<float>::digits * 3010/10000; // == 9
float f = 3.1459F; // a test value - on a
hemidemisemi-random test 1/3 fail.
float rf; // for recalculate.
std::stringstream s;
s.precision(float_significant_decimal_digits); //
9 decimal digits is enough.
s << f; // Output to string.
s >> rf; // Read back in to float.
assert(f == rf); // Check get back the same.
return 0;
} // int main()
--
Paul A Bristow
Prizet Farmhouse, Kendal LA8 8AB UK
[email]pbristow (AT) hetp (DOT) u-net.com[/email]
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
|
|
| Back to top |
|
 |
Victor Bazarov Guest
|
Posted: Fri Oct 15, 2004 3:06 pm Post subject: Re: Should Float(s) to string(stream) be re-input exactly th |
|
|
Paul A Bristow wrote:
| Quote: | Whilest devising tests for the Boost lexical_cast function,
I have encountered (for one compiler version) some surprising (to me)
results outputting
floats to decimal digit strings and reading them back in.
Providing you use enough decimal digits, I expected the result of
this 'loopback' to be the same, for example:
float f = any_float_value; // Similarly for other types, UDTs even?
std::stringstream s;
s.precision(float_significant_decimal_digits); // 9 decimal digits should
be enough (see Appendix below).
s << f; // Output to decimal digit string(stream).
float rf;
s >> rf; // read string back into float.
My expectation is that f == rf for ALL possible float values
(and indeed this WAS true for an exhaustive test with a previous version of
a well-known compiler,
and for a randomish sample of double and long double values).
A recent version outputs the same decimal digit strings
- BUT the value read back in is 1 least significant binary digit different -
suspiciously only for 1/3 of the float values.
(Nor does increasing the number of decimal digits output via s.precision()
change this).
But perhaps this is not a Standard expectation?
|
Standard says nothing about such behaviour. AFAIK the only expectation
one might have is that a number output with certain precision, then
read back, then this new number output with the same precision should
produce the same output.
IMO any other expectation is unreasonable.
V
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
|
|
| Back to top |
|
 |
Simon Richter Guest
|
Posted: Fri Oct 15, 2004 5:26 pm Post subject: Re: Should Float(s) to string(stream) be re-input exactly th |
|
|
Hi,
| Quote: | My expectation is that f == rf for ALL possible float values
|
I believe that operator==(float, float) and operator==(double, double)
should be dropped from the standard, as there is no way this can be
implemented correctly on all architectures and it places a heavy burden
on implementors.
Seriously though, you can only check that the result you get is within a
substantially small distance from the expected result, as for example
the Intel architecture has longer floating point registers than the
actual memory layout, so a value cached on the FP stack may already
differ in the lower order bits when compared to a value from memory
(where these bits are read as zero).
Simon
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
|
|
| Back to top |
|
 |
Alberto Barbati Guest
|
Posted: Fri Oct 15, 2004 5:26 pm Post subject: Re: Should Float(s) to string(stream) be re-input exactly th |
|
|
Paul A Bristow wrote:
| Quote: |
But perhaps this is not a Standard expectation?
|
It's a mathematical fact that not all floating point numbers represented
in a binary base can also be represented *exactly* in a decimal base, no
matter how many digits you use. So the standard does not (because it
can't) have this expectation.
However, it seems that the problem has been acknoledged by the C
community that have introduced a printf/scanf formatter ("%a" IIRC) to
output floating point numbers in a hexadecimal format that would
represent compacly and exactly any floating point number (assuming that
the underlying representation is binary).
It is reasonable to assume that in a few years all C/C++ compilers with
a conformant C9X library will have such feature, so it may be available
to C++ programs also. I believe that the C++ community should do its
part and extend the iostream formatters to allow the hexadecimal format.
That could be quite easily obtained by adding a new ios_base flag in the
floatfield mask and require num_get/num_put to behave accordingly. I
cannot see complex design issue to discuss, so if it's not too late for
that, I wish it could be considered for inclusion in TR1.
Alberto
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
|
|
| Back to top |
|
 |
Victor Bazarov Guest
|
Posted: Sat Oct 16, 2004 7:12 am Post subject: Re: Should Float(s) to string(stream) be re-input exactly th |
|
|
Alberto Barbati wrote:
| Quote: | Paul A Bristow wrote:
But perhaps this is not a Standard expectation?
It's a mathematical fact that not all floating point numbers represented
in a binary base can also be represented *exactly* in a decimal base, no
matter how many digits you use.
|
I think it's the reverse that is true. You cannot, for example, represent
0.1 (one tenth) precisely in binary because it becomes periodic:
Binary: 0.00011001100110011001(1001)
Hex: 0.19999999999999999999(9)
However, any binary fraction can be represented in decimal notation
exactly. You just need a long enough (yet finite) set of decimal digits.
The difference is that the base (1/2) for binary fractions is represented
exactly in the decimal, but the reverse isn't so.
| Quote: | So the standard does not (because it
can't) have this expectation.
|
No. It's the unreasonability of precise representation of what is in the
computer memory combined with the fact that in the computer memory it is
still not the precise number anyway. So, why allow outputting the full
set of needed decimal digits when the number is imprecise anyway?
FLT_EPSILON, for example is 0.00000011920928955078125000000. Precisely.
| Quote: | However, it seems that the problem has been acknoledged by the C
community that have introduced a printf/scanf formatter ("%a" IIRC) to
output floating point numbers in a hexadecimal format that would
represent compacly and exactly any floating point number (assuming that
the underlying representation is binary).
|
It seems that some folks have been doing something similar for ages. It's
basically a text form of the internal binary representation whether you use
%a or just output the underlying chars as %02x. Yes, %a is more readable
and portable. Under more portable I mean that you still are going to lose
some precision if the platform that reads the external representation has
fewer bits representing 'double' than the platform where it was written.
| Quote: | It is reasonable to assume that in a few years all C/C++ compilers with
a conformant C9X library will have such feature, so it may be available
to C++ programs also. I believe that the C++ community should do its
part and extend the iostream formatters to allow the hexadecimal format.
That could be quite easily obtained by adding a new ios_base flag in the
floatfield mask and require num_get/num_put to behave accordingly. I
cannot see complex design issue to discuss, so if it's not too late for
that, I wish it could be considered for inclusion in TR1.
|
I think it's an implementation issue. If you use 'hex' modifier to output
a floating point number, should it just give the analogous format to C99's
%a? The implementers might begin thinking about that already.
V
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
|
|
| Back to top |
|
 |
Alberto Barbati Guest
|
Posted: Sun Oct 17, 2004 6:44 am Post subject: Re: Should Float(s) to string(stream) be re-input exactly th |
|
|
Victor Bazarov wrote:
| Quote: | Alberto Barbati wrote:
It's a mathematical fact that not all floating point numbers
represented in a binary base can also be represented *exactly* in a
decimal base, no matter how many digits you use.
I think it's the reverse that is true. You cannot, for example, represent
0.1 (one tenth) precisely in binary because it becomes periodic:
Binary: 0.00011001100110011001(1001)
Hex: 0.19999999999999999999(9)
However, any binary fraction can be represented in decimal notation
exactly. You just need a long enough (yet finite) set of decimal digits.
The difference is that the base (1/2) for binary fractions is represented
exactly in the decimal, but the reverse isn't so.
|
You're completely right. I apologize, I got it the wrong way round.
| Quote: | However, it seems that the problem has been acknoledged by the C
community that have introduced a printf/scanf formatter ("%a" IIRC) to
output floating point numbers in a hexadecimal format that would
represent compacly and exactly any floating point number (assuming
that the underlying representation is binary).
It seems that some folks have been doing something similar for ages. It's
basically a text form of the internal binary representation whether youuse
%a or just output the underlying chars as %02x.
|
Not exactly. Outputting the underlying chars would be unportable as
internal binary representation may differ among platforms. According to
the C standard %a shall produce a text string formatted like
[−]0xh.hhhhp±d where "h.hhhh" is a hexadecimal number representing the
mantissa, "d" is the (decimal) exponent, "0x" and "p" are taken literally.
| Quote: | Under more portable I mean that you still are going to lose
some precision if the platform that reads the external representation has
fewer bits representing 'double' than the platform where it was written..
|
You're right about that. Yet, it seems that the hex format can be
useful, at least in the C committee's opinion.
| Quote: | It is reasonable to assume that in a few years all C/C++ compilers
with a conformant C9X library will have such feature, so it may be
available to C++ programs also. I believe that the C++ community
should do its part and extend the iostream formatters to allow the
hexadecimal format. That could be quite easily obtained by adding a
new ios_base flag in the floatfield mask and require num_get/num_put
to behave accordingly. I cannot see complex design issue to discuss,
so if it's not too late for that, I wish it could be considered for
inclusion in TR1.
I think it's an implementation issue. If you use 'hex' modifier to output
a floating point number, should it just give the analogous format to C99's
%a? The implementers might begin thinking about that already.
|
We can't "overload" the std::hex modifier, because that would silently
change the behaviour of a program that mix integer and float formatting.
For example:
int main()
{
std::cout << std::hex << 10000 << 10000.0 << "n";
}
There's more. On the input side, C99 changed the scanf "%g" specifier to
allow parsing of the hex fp format and C++ istream parsing for floats is
defined in terms of said specifier (22.2.2.1.2/5). Currently, C++ only
includes the C95 library, but if it will ever "upgrade" to C99 then C++
will get to parse the hex fp format too!
I think the committee should look into this and either clarify that the
hex fp format is disallowed on input or standardize the way such format
is produced on output. I have already located the changes that should be
made to introduce a new ios_base flag (a total of five places). Should I
make a formal proposal?
Alberto
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
|
|
| Back to top |
|
 |
P.J. Plauger Guest
|
Posted: Sun Oct 17, 2004 8:43 pm Post subject: Re: Should Float(s) to string(stream) be re-input exactly th |
|
|
"Alberto Barbati" <AlbertoBarbati (AT) libero (DOT) it> wrote
| Quote: | It is reasonable to assume that in a few years all C/C++ compilers with a
conformant C9X library will have such feature, so it may be available to
C++ programs also. I believe that the C++ community should do its part
and extend the iostream formatters to allow the hexadecimal format. That
could be quite easily obtained by adding a new ios_base flag in the
floatfield mask and require num_get/num_put to behave accordingly. I
cannot see complex design issue to discuss, so if it's not too late for
that, I wish it could be considered for inclusion in TR1.
I think it's an implementation issue. If you use 'hex' modifier to output
a floating point number, should it just give the analogous format to C99's
%a? The implementers might begin thinking about that already.
|
We can't "overload" the std::hex modifier, because that would silently
change the behaviour of a program that mix integer and float formatting.
For example:
int main()
{
std::cout << std::hex << 10000 << 10000.0 << "n";
}
There's more. On the input side, C99 changed the scanf "%g" specifier to
allow parsing of the hex fp format and C++ istream parsing for floats is
defined in terms of said specifier (22.2.2.1.2/5). Currently, C++ only
includes the C95 library, but if it will ever "upgrade" to C99 then C++
will get to parse the hex fp format too!
I think the committee should look into this and either clarify that the
hex fp format is disallowed on input or standardize the way such format
is produced on output. I have already located the changes that should be
made to introduce a new ios_base flag (a total of five places). Should I
make a formal proposal?
[pjp] You can if you want, but the (non-normative) library TR1 already
incorporates such a mechanism. It is based on the work we at
Dinkumware did several years ago in integrating C99 and C++.
P.J. Plauger
Dinkumware, Ltd.
http://www.dinkumware.com
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
|
|
| Back to top |
|
 |
kanze@gabi-soft.fr Guest
|
Posted: Mon Oct 18, 2004 4:40 pm Post subject: Re: Should Float(s) to string(stream) be re-input exactly th |
|
|
[email]richtesi (AT) informatik (DOT) tu-muenchen.de[/email] (Simon Richter) wrote in message
news:<ckod3g$p9d$02$1 (AT) news (DOT) t-online.com>...
| Quote: | My expectation is that f == rf for ALL possible float values
I believe that operator==(float, float) and operator==(double, double)
should be dropped from the standard, as there is no way this can be
implemented correctly on all architectures and it places a heavy
burden on implementors.
|
I can't speak for all architectures, but it is trivial to implement on
the two I know well, Intel IA32 and Sparc. There's no more burden on
implementors here than for operator==( int, int ).
There is, of course, more burden on users to use them correctly.
Correct floating point is a lot trickier than correct integral
arithmetic.
| Quote: | Seriously though, you can only check that the result you get is within
a substantially small distance from the expected result, as for
example the Intel architecture has longer floating point registers
than the actual memory layout, so a value cached on the FP stack may
already differ in the lower order bits when compared to a value from
memory (where these bits are read as zero).
|
The original poster spoke of values actually assigned to float
variables. The number of bits in a float are fixed. Given everything
that has happened since the assignment to the first float, and the fact
that the second float is assigned through a non-const reference in a
library routine, I would be very surprised if either of the values
represented the results of a calculation which didn't get stored back in
memory. It's a distant possibility, but when he speaks of the LSB being
off in 1/3 of the values, it's obvious that this cannot be his problem.
For the rest, with sufficient digits (and nine is sufficient for IEEE
single precision floating point), the results of the conversion, in both
ways, is exactly defined, AND the conversion should be round trip.
--
James Kanze GABI Software http://www.gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
|
|
| Back to top |
|
 |
kanze@gabi-soft.fr Guest
|
Posted: Mon Oct 18, 2004 11:25 pm Post subject: Re: Should Float(s) to string(stream) be re-input exactly th |
|
|
[email]v.Abazarov (AT) comAcast (DOT) net[/email] (Victor Bazarov) wrote in message
news:<vPQbd.4940$Ae.4915 (AT) newsread1 (DOT) dllstx09.us.to.verio.net>...
| Quote: | Paul A Bristow wrote:
Whilest devising tests for the Boost lexical_cast function, I have
encountered (for one compiler version) some surprising (to me)
results outputting floats to decimal digit strings and reading them
back in.
Providing you use enough decimal digits, I expected the result of
this 'loopback' to be the same, for example:
float f = any_float_value; // Similarly for other types, UDTs even?
std::stringstream s;
s.precision(float_significant_decimal_digits); // 9 decimal digits should
be enough (see Appendix below).
s << f; // Output to decimal digit string(stream).
float rf;
s >> rf; // read string back into float.
My expectation is that f == rf for ALL possible float values (and
indeed this WAS true for an exhaustive test with a previous version
of a well-known compiler, and for a randomish sample of double and
long double values).
A recent version outputs the same decimal digit strings
- BUT the value read back in is 1 least significant binary digit
different - suspiciously only for 1/3 of the float values.
(Nor does increasing the number of decimal digits output via
s.precision() change this).
But perhaps this is not a Standard expectation?
Standard says nothing about such behaviour. AFAIK the only
expectation one might have is that a number output with certain
precision, then read back, then this new number output with the same
precision should produce the same output.
IMO any other expectation is unreasonable.
|
The standard effectively sets no requirements concerning the precision
of the conversions on input or output. Quality of implementation does,
however, as does IEEE (IIRC). If the floating point format on the
machine he is using is IEEE, I would consider the behavior he describes
defective, if only from a quality of implementation point of view.
--
James Kanze GABI Software http://www.gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
|
|
| Back to top |
|
 |
Alberto Barbati Guest
|
Posted: Tue Oct 19, 2004 6:25 am Post subject: Re: Should Float(s) to string(stream) be re-input exactly th |
|
|
P.J. Plauger wrote:
| Quote: |
[pjp] You can if you want, but the (non-normative) library TR1 already
incorporates such a mechanism. It is based on the work we at
Dinkumware did several years ago in integrating C99 and C++.
|
I see. I guess you refer to paper N1568. The paper chooses the value
ios_base::fixed | ios_base::scientific to require the hexadecimal format.
Sure, that approach requires the least number of changes and gets the
job done, but looks a bit unnatural to me because %a is not a fixed
format. In fact the C standard says "if the precision is missing then
the precision is sufficient for an exact representation of the value"
oppositely of the %f specifier when there is a default value of exactly
6 digits.
Moreover, the value ios_base::fixed | ios_base::scientific, although
very rarely used, falled back in pre-TR1 libraries to %g formatting and
that raises a couple of compatibility issues:
1) An pre-TR1 program built with a TR1 library may experience a silent
behaviour change;
2) A TR1 program that relies on hexadecimal fp formatting will silently
build even with a pre-TR1 library with a behaviour change.
My proposal is to add a new constant. Although more intrusive, the
modification are still very few and none of the above objections would
hold. Here they are:
Clause 22.2.2.2.2
In table 58, after the line:
floatfield == ios_base::scientific %E
add the lines:
floatfield == ios_base::hexfloat && !uppercase %a
floatfield == ios_base::hexfloat %A
Clause 27.4
In the <ios> header synopsis, after the line:
ios_base& scientific (ios_base& str);
add the line:
ios_base& hexfloat (ios_base& str);
Clause 27.4.2
In the ios base class synopsis, after the line:
static const fmtflags scientific;
add the line:
static const fmtflags hexfloat;
Clause 27.4.2.1.2
In table 83 (fmtflags effect) add the line:
hexfloat generates floating-point output in hexadecimal notation;
In table 84 (fmtflags constants) replace the line:
floatfield scientific | fixed
with the line
floatfield scientific | fixed | hexfloat
Clause 27.4.5.4
Add the following paragraphs:
ios_base& hexfloat(ios_base& str);
5 Effects: Calls str.setf(ios_base::scientific, ios_base::hexfloat).
6 Returns: str.
The choice of the name "hexfloat" is quite arbitrary and is subject to
discussion.
Alberto
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
|
|
| Back to top |
|
 |
Paul A Bristow Guest
|
Posted: Wed Oct 20, 2004 12:29 pm Post subject: Re: Should Float(s) to string(stream) be re-input exactly th |
|
|
Thanks to all who replied to my query.
Since the values output are the same as in a previously successful loopback
test, I think it is reasonable to assume that the problem is not with
output, but with INPUT.
Some of the discussion veered off onto the method of inputting in hex, but I
feel that it another issue (and is, of course, tiresome to make portable
because it is dependent on the particular floating point format, as is using
exactly representable decimal digit strings).
The results are the same using an even simpler test
float f = 3.14590000f; // 9 decimal digits
cout << f;
float rf;
cin >> rf;
cout << rf;
assert(f == rf);
And results are:
3.14590001
3.14590025
Assertion failed: f == rf, file .Hello.cpp, line 50
These are the decimal digits string representations of binary values which
differ by the least significant significand bit
f = 3.14590014F is the next to succeed.
Significantly, using "exactly representable" values, for example for pi
const float pi_l = 3.1415925025939941406250F; // Upper and lower limits of
pi using IEEE 24 bit significand float.
succeeds with 9 digits 3.14159250
but fails for the upper limit (1 bit more) 3.14159274
const float pi_u = 3.1415927410125732421875F;
I conclude that whilest the Standard is not quite explicit about an accuracy
requirement, this counts as a bug rather than a feature.
Although apparently quite minor, I fear it may cause considerable confusion
from small differences in some computed results.
Thanks
Paul
""Paul A Bristow""
| Quote: | Whilest devising tests for the Boost lexical_cast function,
I have encountered (for one compiler version) some surprising (to me)
results outputting
floats to decimal digit strings and reading them back in.
Providing you use enough decimal digits, I expected the result of
this 'loopback' to be the same, for example:
float f = any_float_value; // Similarly for other types, UDTs even?
std::stringstream s;
s.precision(float_significant_decimal_digits); // 9 decimal digits
should
be enough (see Appendix below).
s << f; // Output to decimal digit string(stream).
float rf;
s >> rf; // read string back into float.
My expectation is that f == rf for ALL possible float values
(and indeed this WAS true for an exhaustive test with a previous version
of
a well-known compiler,
and for a randomish sample of double and long double values).
A recent version outputs the same decimal digit strings
- BUT the value read back in is 1 least significant binary digit
different -
suspiciously only for 1/3 of the float values.
(Nor does increasing the number of decimal digits output via s.precision()
change this).
But perhaps this is not a Standard expectation?
Paul Bristow
|
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
|
|
| Back to top |
|
 |
Alberto Barbati Guest
|
Posted: Thu Oct 21, 2004 7:07 am Post subject: Re: Should Float(s) to string(stream) be re-input exactly th |
|
|
Paul A Bristow wrote:
| Quote: |
Some of the discussion veered off onto the method of inputting in hex, but I
feel that it another issue (and is, of course, tiresome to make portable
because it is dependent on the particular floating point format, as is using
exactly representable decimal digit strings).
|
You don't seem to have understood what the hex fp format is. The hex fp
format *does not* depend on the implementation of floating point and is
supposed to be as portable as the "regular" scientific format. As I
wrote in my post, the hex fp format is a string like [−]0xh.hhhhp±d
where "h.hhhh" is a hexadecimal number representing the mantissa and "d"
is a decimal number representing the exponent. It's *exactly the same*
as the scientific format, except that the mantissa is expressed as an
hexadecimal instead of a decimal number. The advantage is that if
FLT_RADIX is a power of 2, you can do exact I/O (both exact output *and*
exact input!) using a finite number of digits. If FLT_RADIX is not a
power of 2 it's no better and no worse than the "regular" scientific
format (unless FLT_RADIX is either 5 of a multiple of 10... which I
believe it's rather rare in practice).
Alberto
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
|
|
| Back to top |
|
 |
kanze@gabi-soft.fr Guest
|
Posted: Fri Oct 22, 2004 5:37 pm Post subject: Re: Should Float(s) to string(stream) be re-input exactly th |
|
|
[email]AlbertoBarbati (AT) libero (DOT) it[/email] (Alberto Barbati) wrote in message
news:<gXtdd.49586$N45.1462626 (AT) twister2 (DOT) libero.it>...
| Quote: | Paul A Bristow wrote:
Some of the discussion veered off onto the method of inputting in
hex, but I feel that it another issue (and is, of course, tiresome
to make portable because it is dependent on the particular floating
point format, as is using exactly representable decimal digit
strings).
You don't seem to have understood what the hex fp format is. The hex
fp format *does not* depend on the implementation of floating point
and is supposed to be as portable as the "regular" scientific
format. As I wrote in my post, the hex fp format is a string like
[?]0xh.hhhhp ±d where "h.hhhh" is a hexadecimal number representing
the mantissa and "d" is a decimal number representing the
exponent. It's *exactly the same* as the scientific format, except
that the mantissa is expressed as an hexadecimal instead of a decimal
number. The advantage is that if FLT RADIX is a power of 2, you can do
exact I/O (both exact output *and* exact input!) using a finite number
of digits.
|
You can also do that with decimal; 2 is a factor of 10. The difference
is that with hex format, the conversion is a lot simpler, with less
risque of rounding errors in the conversion routines. And with less
total digits.
| Quote: | If FLT RADIX is not a power of 2 it's no better and no worse than the
"regular" scientific format (unless FLT RADIX is either 5 of a
multiple of 10... which I believe it's rather rare in practice).
|
I've only seen three FLT_RADIX in practice: 2, 16 and 10. Rare is a
matter of appreciation -- I'm pretty sure that 10 is less common than 2
or 16 today, but it is certainly more frequent than any other value.
(Actually, I'm not sure of that. Most general purpose processors today
use IEEE, which is base 2, but I think that a lot of smaller, hand-held
processors use base 10. I don't think any of them have a C++ compiler,
but who knows.)
--
James Kanze GABI Software http://www.gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
|
|
| Back to top |
|
 |
Andrew Koenig Guest
|
Posted: Sat Oct 23, 2004 4:38 pm Post subject: Re: Should Float(s) to string(stream) be re-input exactly th |
|
|
<kanze (AT) gabi-soft (DOT) fr> wrote
| Quote: | AlbertoBarbati (AT) libero (DOT) it (Alberto Barbati) wrote in message
news:<gXtdd.49586$N45.1462626 (AT) twister2 (DOT) libero.it>...
The advantage is that if FLT RADIX is a power of 2, you can do
exact I/O (both exact output *and* exact input!) using a finite number
of digits.
You can also do that with decimal; 2 is a factor of 10. The difference
is that with hex format, the conversion is a lot simpler, with less
risque of rounding errors in the conversion routines. And with less
total digits.
|
Ummm...not quite.
It is true that every binary floating-point number has an exact decimal
representation. However, it is not true that every decimal floating-point
number has an exact binary representation.
More generally, if you wish to read a decimal representation of a
floating-point number and compute the nearest binary floating-point value to
what you read, you need unbounded-precision arithmetic to do it correctly in
all cases. If, on the other hand, the representation is binary or hex, you
don't.
It is true that you might need to examine all of the input bits to determine
the correct rounding of the result, but you don't need unbounded-precision
arithmetic to do that -- instead, you can (if needed) get into a mode where
you scan bits looking for a 1 or a zero (depending on rounding mode) and
stop when you find it.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
|
|
| Back to top |
|
 |
Hyman Rosen Guest
|
Posted: Sun Oct 24, 2004 8:45 pm Post subject: Re: Should Float(s) to string(stream) be re-input exactly th |
|
|
Alberto Barbati wrote:
| Quote: | The advantage is that if FLT_RADIX is a power of 2,
you can do exact I/O (both exact output *and* exact input!)
using a finite number of digits.
|
Of course this is equally true for decimal I/O!
Every binary floating point number can be written
exactly using a finite number of decimal digits.
This whole topic comes up over and over. There are
a pair of classic papers which were published in a
SIGPLAN proceedings which discuss how to write and
read floating point numbers. The upshot is that
there is a way to convert a decimal string to its
nearest floating point representation, and a way to
write a shortest decimal string such that the read
algorithm will convert it back to the original value.
That's all that's really needed.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|