Floating point truncation bug in qi::float_

Hi I am using boost 1.4.1 Spirit::Qi. I think we have a floating point truncation bug in the qi::float_ parser. I attached a simple program to repro the bug. Below are some examples of an input floating point gets truncated (=>) by the qi::float_: 12312321421421 => 12312321720320.000000 123123214 => 123123216.000000 123233.4124 => 123233.406250 I don't see the same issue with the qi::double_. Wondering if this is a known issue? Regards, HTan

On 9/28/2010 1:12 PM, Henry Tan wrote:
Without being too familiar with the qi::float_ parser, I would guess it rounds rather than truncates. Keep in mind that floats are typically 32-bit single precision [1], hence have only 24 significant bits (a bit more than 7 significant decimal digits), which is consistent with your results. On the other hand, doubles are typically 64-bit double precision [2], hence have 53 significant bits (a bit under 16 significant decimal digits), so the first 2 inputs above would be stored exactly, and the 3rd one would be pretty close. - Jeff [1] http://en.wikipedia.org/wiki/Single_precision_floating-point_format [2] http://en.wikipedia.org/wiki/Double_precision_floating-point_format

With newer compiler/standard libraries #include <limits> allows you to automatically get all the potentially significant digits using the new max_digits10 cout.precision(std::numeric_limits<double>::max_digits10); And remember that *input* of a string of decimal digits from a stream is *not guaranteed* by the C++ Standard to produce the nearest representable value. It could be one bit up or one bit down. It does work to exact representation (as the compiler does from literals) nearly all the time (and I have confirmed that for floats it is all the time - you can test every single floating point value in a reasonable time - overnight!) but not necessarily for double. For Microsoft, there are tiny range of doubles for which the result is 1 bit 'wrong'. The workaround is simple - use scientific format with max_digits10 . Details at http://lab.msdn.microsoft.com/ProductFeedback/viewfeedback.aspx?feedbackid=c 1f1ea71-2f7b-4ac1-b75b-68370c367aae aka http://tinyurl.com/rvp4j It's a feature, not a bug. Paul --- Paul A. Bristow, Prizet Farmhouse, Kendal LA8 8AB UK +44 1539 561830 07714330204 pbristow@hetp.u-net.com

If I do: #include <iostream> #include <iomanip> int main() { float f1 = 12312321421421.f; float f2 = 123123214.f; float f3 = 123233.4124f; std::cout.precision(20); std::cout << "12312321421421 --> " << f1 << std::endl; std::cout << "123123214 --> " << f2 << std::endl; std::cout << "123233.4124 --> " << f3 << std::endl; return 0; } I get (gcc 4.5.1 and VS2010): 12312321421421 --> 12312321720320 123123214 --> 123123216 123233.4124 --> 123233.4140625 which is almost consistent with what Spirit is doing. The last case worries me, though. I'll try to have a closer look there. Regards Hartmut --------------- http://boost-spirit.com
participants (5)
-
Hartmut Kaiser
-
Henry Tan
-
Jeffrey Lee Hellrung, Jr.
-
OvermindDL1
-
Paul A. Bristow