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: Jonathan Jones <jonathan.jones@…> 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)

lexical_cast.cpp (1.8 KB ) - added by Jonathan Jones <jonathan.jones@…> 10 years ago.

Download all attachments as: .zip

Change History (5)

by Jonathan Jones <jonathan.jones@…>, 10 years ago

Attachment: lexical_cast.cpp added

comment:1 by Antony Polukhin, 10 years ago

Severity: ProblemCosmetic
Status: newassigned
Type: BugsSupport Requests

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

in reply to:  1 ; comment:2 by Jonathan Jones <jonathan.jones@…>, 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.

in reply to:  2 comment:3 by Antony Polukhin, 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 Antony Polukhin, 8 years ago

Milestone: To Be DeterminedBoost 1.58.0
Resolution: fixed
Status: assignedclosed

Since Boost 1.58 lexical_cast must use converters from Standard Library, so that issue must be already resolved on Standard Library level.

Note: See TracTickets for help on using tickets.