[lexical_cast] Assumed internal double conversion of float?

Hi Boost experts, We are chasing down some test failures with floats on VxWorks using the Dinkum clib and c++lib. We are testing with clang on Intel and Arm targets and GCC on PowerPC targets. An example failure at the bottom of this email. We have determined that boost::detail::lcast_get_precision<float>() is returning 9, well in access of the defined FLT_DIG of 6, or the practical float limit of 6.92. Specifically this code here: bool shl_real_type(float val, char* begin) { using namespace std; const double val_as_double = val; finish = start + #if defined(_MSC_VER) && (_MSC_VER >= 1400) && !defined(__SGI_STL_PORT) && !defined(_STLPORT_VERSION) sprintf_s(begin, CharacterBufferSize, #else sprintf(begin, #endif "%.*g", static_cast<int>(boost::detail::lcast_get_precision<float>()), val_as_double); return finish > start; } Where does boost::detail::lcast_get_precision<float>() come from, and why is it 9 ? Is it perhaps assuming some intermediate double conversion internally? In Dinkum's C library, Plager conservatively does not promote to a double, when converting to a string. Many thanks, Brian Wind River ->cmd "LD_LIBRARY_PATH=/opt/TestTriggerLocalPath/Workspace/vx7-boost/2019-01-13/vsb/app/boost/fsl_imx6_llvm_up_32_vxWorks/usr/root/llvm/bin;/opt/TestTriggerLocalPath/Workspace/vx7-boost/2019-01-13/vsb/app/boost/fsl_imx6_llvm_up_32_vxWorks/usr/lib/common" [vxWorks *]# cd /opt/TestTriggerLocalPath/Workspace/vx7-boost/2019-01-13/vsb/app/boost/fsl_imx6_llvm_up_32_vxWorks/3pp/BOOST/boost_1_68_0/status [vxWorks *]# run -x -t 0x01000000 -u 100000 -- ../bin.v2/libs/lexical_cast/test/lexical_cast_float_types_test.test/clang-vxworks/debug/cross-compile-vxworks/static-only-on/lexical_cast_float_types_test.vxe Launching process '../bin.v2/libs/lexical_cast/test/lexical_cast_float_types_test.test/clang-vxworks/debug/cross-compile-vxworks/static-only-on/lexical_cast_float_types_test.vxe' ... Process '../bin.v2/libs/lexical_cast/test/lexical_cast_float_types_test.test/clang-vxworks/debug/cross-compile-vxworks/static-only-on/lexical_cast_float_types_test.vxe' (process Id = 0x20482f10) launched. Running 3 test cases... unknown location(0): [4;31;49mfatal error: in "lexical_cast float types unit test/test_conversion_from_to_double": boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::bad_lexical_cast>
: bad lexical cast: source type value could not be interpreted as target [0;39;49m ../libs/lexical_cast/test/lexical_cast_float_types_test.cpp(299): [1;36;49mlast checkpoint [0;39;49m unknown location(0): [4;31;49mfatal error: in "lexical_cast float types unit test/test_conversion_from_to_long_double": boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::bad_lexical_cast> : bad lexical cast: source type value could not be interpreted as target [0;39;49m ../libs/lexical_cast/test/lexical_cast_float_types_test.cpp(299): [1;36;49mlast checkpoint [0;39;49m

Brian Kuhl wrote:
Where does boost::detail::lcast_get_precision<float>() come from, and why is it 9 ? Is it perhaps assuming some intermediate double conversion internally?
boost::detail::lcast_get_precision<double>() is 17, so no. My guess is that this is the precision that guarantees a perfect roundtrip.

Note that there are two numbers of digits that are of interest: If you take a decimal number, convert it to float, and convert it back to decimal, how many decimal digits are guaranteed to survive unchanged? If you take a float, convert it to decimal, and convert it back to float, how many decimal digits are required to always get all bits of the original float correct? For 32-bit float, the answers are 6 and 9, respectively. For 64-bit double, it's 15 and 17. See: https://www.exploringbinary.com/number-of-digits-required-for-round-trip-con... As an aside: when converting a string to a floating-point number, it is incorrect to round twice - i.e. you cannot implement strtof by calling strtod and then rounding double to float. STL -----Original Message----- From: Boost <boost-bounces@lists.boost.org> On Behalf Of Peter Dimov via Boost Sent: Tuesday, January 29, 2019 9:42 AM To: boost@lists.boost.org Cc: Peter Dimov <lists@pdimov.com> Subject: Re: [boost] [lexical_cast] Assumed internal double conversion of float? Brian Kuhl wrote:
Where does boost::detail::lcast_get_precision<float>() come from, and why is it 9 ? Is it perhaps assuming some intermediate double conversion internally?
boost::detail::lcast_get_precision<double>() is 17, so no. My guess is that this is the precision that guarantees a perfect roundtrip. _______________________________________________ Unsubscribe & other changes: https://nam06.safelinks.protection.outlook.com/?url=http%3A%2F%2Flists.boost...

-----Original Message----- From: Boost [mailto:boost-bounces@lists.boost.org] On Behalf Of Brian Kuhl via Boost Sent: 29 January 2019 17:28 To: boost@lists.boost.org Cc: Brian Kuhl; adrian.park@windriver.com Subject: [boost] [lexical_cast] Assumed internal double conversion of float?
Hi Boost experts, We are chasing down some test failures with floats on VxWorks using the Dinkum clib and c++lib. We are testing with clang on Intel and Arm targets and GCC on PowerPC targets. An example failure at the bottom of this email.
We have determined that boost::detail::lcast_get_precision<float>() is returning 9, well in access of the defined FLT_DIG of 6, or the practical float limit of 6.92.
It returns std::numeric_limits<float>::maxdigits_10 = 9 This is maximum number of decimal digits that can contain information. Any more are just noise. std::numeric_limits<float>::digits_10 = 6 This is the number of decimal digits that are certain to be correct. The other 3 digits are 'noisy'. Our ancestors should have just used their fingers, and not their thumbs ;-) HTH Paul --- Paul A. Bristow Prizet Farmhouse Kendal UK LA8 8AB +44 (0) 1539 561830
participants (4)
-
Brian Kuhl
-
Paul A. Bristow
-
Peter Dimov
-
Stephan T. Lavavej