Opened 10 years ago
Closed 8 years ago
#6975 closed Support Requests (fixed)
lexical_cast<double> produces different answers with 53-bit FPU precision
Reported by: | Owned by: | Antony Polukhin | |
---|---|---|---|
Milestone: | Boost 1.58.0 | Component: | lexical_cast |
Version: | Boost 1.49.0 | Severity: | Cosmetic |
Keywords: | Cc: |
Description
For some subset of floating point strings, if you use lexical_cast<double>, it will produce different answers than if you use std::atof or reading from std::istringstream. However, this only happens when you use 53 bit FPU precision as opposed to 64 bit.
A duplication program is attached, which I've only tried on g++/64 bit-Intel because of the code modifying the FPU settings.
Attachments (1)
Change History (5)
by , 10 years ago
Attachment: | lexical_cast.cpp added |
---|
follow-up: 2 comment:1 by , 10 years ago
Severity: | Problem → Cosmetic |
---|---|
Status: | new → assigned |
Type: | Bugs → Support Requests |
follow-up: 3 comment:2 by , 10 years ago
Replying to apolukhin:
This issue won't be fixed in nearest future (it shall be fixed in ticket #5660)
Do you have a rough estimate of the timeframe in which it will be fixed?
When casting to doubles, lexical_cast uses long doubles for getting better precision and assumes that long doubles precision set to 64 (default). But even with 53bit precision result is accurate enougth, so this bug is not critical.
It's the double->string->double issue, as mentioned in ticket #5660, which is problematic for us. Doubles which should be serializable to a string and back to a double with no change are returning slightly different answers from the original double.
By the way: you shall not compare floats using == and != operatos. See http://www.parashift.com/c++-faq-lite/floating-point-arith.html
I understand that this is true in the general case, but in our case the floats we are comparing are pre-calculated numbers which are exactly representable (not approximated) in floating point.
FWIW, we've worked around the problem by forcing lexical_cast to always use:
float_types_converter_internal(T& output, int /*tag*/)
which doesn't seem to suffer from the same issue. It's only lcast_ret_float<Traits> which has the problem.
comment:3 by , 10 years ago
Replying to Jonathan Jones <jonathan.jones@…>:
Replying to apolukhin:
This issue won't be fixed in nearest future (it shall be fixed in ticket #5660)
Do you have a rough estimate of the timeframe in which it will be fixed?
I do not think that it would be fixed in nearest two releases of boost.
<snip>
FWIW, we've worked around the problem by forcing lexical_cast to always use:
float_types_converter_internal(T& output, int /*tag*/)
which doesn't seem to suffer from the same issue. It's only lcast_ret_float<Traits> which has the problem.
It is good enough solution, but it may also return slightly different answers for some numbers on MSVC, older versions of GCC and non popular compilers. And this solution is slightly slower (but I do not think that you will notice it)
comment:4 by , 8 years ago
Milestone: | To Be Determined → Boost 1.58.0 |
---|---|
Resolution: | → fixed |
Status: | assigned → closed |
Since Boost 1.58 lexical_cast must use converters from Standard Library, so that issue must be already resolved on Standard Library level.
This issue won't be fixed in nearest future (it shall be fixed in ticket #5660) When casting to doubles, lexical_cast uses long doubles for getting better precision and assumes that long doubles precision set to 64 (default). But even with 53bit precision result is accurate enougth, so this bug is not critical.
By the way: you shall not compare floats using == and != operatos. See http://www.parashift.com/c++-faq-lite/floating-point-arith.html