On Thu, Apr 30, 2009 at 11:49 AM, Grant Birchmeier
On Thu, Apr 30, 2009 at 12:20 PM, Peter Dimov
wrote: (1) Is there a way to eliminate this trailing '1' with lexical_cast (presumably some wierd rounding error)?
Try this code:
std::cout << f2 << std::endl; std::cout << boost::lexical_caststd::string(f2) << std::endl;
std::cout << f - f2 << std::endl;
which will hopefully answer your question.
The resulting output from your code, Peter, is: 123.123 123.123001 123.123 123.123001 0
That's just great. So internally (on my system, anyway) the two floats are equal, and the two methods of converting it to string just round it differently. Curses.
It might help to read up on the IEEE floating point standards. Basically 'most' floating point numbers you will give a computer are incapable of being representing accurately by the CPU in just 32-bits (there are a couple bignum floating point libraries that retain accuracy quite well, obviously much slower). std::cout was just truncating the printed value (which you can control by passing an attribute to the stream to, say, not do any rounding/truncation). Boost.Lexical_cast uses StreamStream internally, and rounding seems to be off, which is good because then it represents the internal number accurately when printed. This is also why you *NEVER* (and this is important enough to say again, ***NEVER***) directly compare floats for equality, there can be arbitrary accuracy in the number. Example: bool FloatsEqual(float f1, float f2) { return f1=f2; } A more proper implementation would be: bool FloatsEqual(float f1, float f2, float eps=0.00001) { return eps>(f1-f2); } The second implementation does a subtraction first to get them to as close to zero as possible if they are near equal. And if the floats had a lot of operations on them and their representations got off (try comparing ((1-0.33333)+0.66666)==1.0 without constant folding... it fails, the left ends up being 0.999998 or so), this will let you pass an 'accuracy' value, the epsilon (there is also an epsilon calculation function in the std namespace). So instead of if(f1==f2) {... You should do something like (with whatever accuracy you want): if(0.00001<(f1-f2)) {...