Bug ID: FDBK17026 Problem Type: Bug Status: Closed Resolution: By Design Microsoft Status: Reviewed Opened Date: 2004-10-24 09:54:41 Opened By: Paul A Bristow Product/Technology: Visual C++ Version: Visual C++ 2005 Express Beta 1 Category: Libraries OS: Windows 2000 Professional OS Language: US English Description: Opened by Paul A Bristow on 2004-10-24 at 09:54:41 Input from decimal digits strings via streams to float is inaccurate by 1 least significant bit in 1/3 of possible values. So flor example float f; cin >> f; does not always give the correct float value. This is a regression from <= 7.1. double and long double still work as expected. This will cause very many very difficult to diagnose problems because equalities like the test given will fail. For example it already makes it impossible to calculate the above exactly representable values. This has already been reported via the C++ Whidby newsgroup and investigation promised. Resolved as By Design by Microsoft on 2004-10-24 at 13:20:28 Thanks for you report. However, it's never appropriate to assume that floating point values can be exactly equivalent after being operated on. You need to use EPSILON or similar to test for equivalence. You shouldn't rely on straight FP equivalency. The change happened because the required values are not representable internally. It used to be different in 7.1 because we used doubles internally for serialising floats, whereas now we respect user intent and use floats to operate on floats -- we use float for the intermediate, decimal shifted result and we can't fit that precisely in a float. Even if we used doubles for intermediate results on floats, we'd experience the same issues with doubles, where we don't have a larger type. Martyn Edited by Microsoft on 2004-10-25 at 10:50:12 Thank you for submitting this to us. We will investigate and keep you informed. Visual C++ Team Steps to Reproduce: Simple test is: float f =3.1459; cout.precision(9); // 9 for 24 significand float (see newsgroup for details of why 9) cout << f; float rf; // for return. cin >> rf; // or use a stringstream cout << rf; assert(rf == f); // Should be true for ALL values of f Also fails for "exactly representable values" const float pi_l = 3.1415925025939941406250F; // Upper and lower limits of pi using 24 bit significand float. const float pi_u = 3.1415927410125732421875F; // exactly representable values. A exhastive test needs float nextafterf(float, float) which is STILL missing. (double version will not do, of course). I have code for this from Sun and PJP has it in C99). I can provide/perform this full test on request - takes overnight. The double and long double tests take a little longer ;-) Actual Results: fails - is 1 least significant wrong for about 1/3 (suspicious?) of test values Expected Results: output of float (using enough digits = 9 for 32 bit IEEE reals) and reinput using a stream (istream fstream or sstream) should give EXACTLY the same binary float value.