[Boost-bugs] [Boost C++ Libraries] #4334: Patch lexical_cast (#4184 + fix to allow casts from string representations of floats to ints)

Subject: [Boost-bugs] [Boost C++ Libraries] #4334: Patch lexical_cast (#4184 + fix to allow casts from string representations of floats to ints)
From: Boost C++ Libraries (noreply_at_[hidden])
Date: 2010-06-11 05:56:37


#4334: Patch lexical_cast (#4184 + fix to allow casts from string representations
of floats to ints)
------------------------------------------+---------------------------------
 Reporter: admin@… | Owner: nasonov
     Type: Patches | Status: new
Milestone: Boost 1.43.0 | Component: lexical_cast
  Version: Boost 1.44.0 | Severity: Problem
 Keywords: float int lexical conversion |
------------------------------------------+---------------------------------
 This patch (hopefully) fixes
 [https://svn.boost.org/trac/boost/ticket/4119] (more details explained in
 my reply in that ticket). Additionally, this patches lexical_cast to
 convert string representations of floats to integers properly.

 An attempt to convert a string representation of a floating point unit
 ("42.5", "500.125", etc) to an integer would throw a bad cast exception.
 This happened because the operator>> members in the lexical_cast stream
 classes returned:

 {{{
 return stream >> output && stream.get() == Traits::eof();
 }}}

 The boost::lexical_cast function evalutes this return value, throwing an
 exception if the return was false. The second half of the return value,
 ''stream.get() == Traits::eof();'', returns false when boost::lexical_cast
 is invoked to convert a string representation of a float to an integer,
 because extraction from the stream to an integer would stop once the
 decimal point was encountered.

 For example, if "17.6" was being converted from a character sequence to an
 integer, the ''stream >> output'' call would extract "17" from the the
 stream to the integer. The last two characters, ".6", would still be in
 the stream, causing ''stream.get() == Traits::eof();'' to return false.

 The solution is pretty simple - when converting from a string
 representation of a floating point unit to an integer, we simply extract a
 float from the stream after extracting the integer. This leaves us with an
 integer, a floating point unit (range 0 to 1), and an empty stream.

 The floating point unit is rounded (floored if below 0.5, ceiled if above
 0.5. The float is always floored if adding it to the integer would cause
 the integer to overflow), and then added to the integer.

 Results of a test program, using unpatched boost::lexical_cast:

 {{{
 wash_at_Pegasus:~/sandbox/concept-test/boost$ ./string_float_to_int_unpatched
 "42.6" as int 0
 "2147483646.9999" as int 0
 "800.0001" as int 0
 }}}

 After:


 {{{
 wash_at_Pegasus:~/sandbox/concept-test/boost$ ./string_float_to_int_patched
 "42.6" as int 43
 "2147483646.9999" as int 2147483646
 "800.0001" as int 800
 }}}

-- 
Ticket URL: <https://svn.boost.org/trac/boost/ticket/4334>
Boost C++ Libraries <http://www.boost.org/>
Boost provides free peer-reviewed portable C++ source libraries.

This archive was generated by hypermail 2.1.7 : 2017-02-16 18:50:03 UTC