1

This is a snippet of my code. I need some help in removing the error shown below.

#include <iostream>
#include <string>
#include <sstream>

int main()
{
    char doubleStr[] = "5.2";
    double d = 0.0;
    std::stringstream stream (doubleStr);
    stream >> d;
    std::cout << d << std::endl;
    std::cout << (d <= 5.2);
    return 0;
}

This gives output:

5.200000000002
0

How to remove this precision error? Can I use std::setprecision() to solve the issue?

  • You will almost always have some inprecision when storing doubles. The exact value "5.2" cannot be stored in a double. With `std::setprecision` you should be able to show less digits, which will look "as if" it was exactly 5.2 – oLen Dec 18 '15 at 12:19
  • 2
    @oLen Something more complicated than that is going on here. Floating point behaviour is predictable and deterministic, just tricky to understand sometimes. Can you explain why parsing `"5.2"` into a `double` is leading to a value not equal to the `double` literal `5.2`? I think they should result in the same double representation, if the compiler and the stream library are both implemented correctly. With gcc 4.9.2, that comparison comes up true. – BoBTFish Dec 18 '15 at 12:22
  • What compiler+os are you using? With gcc 4.9.2, 64bit Linux, I see that comparison coming up true. – BoBTFish Dec 18 '15 at 12:27
  • This must just be a code snipit. The default precision for a stream is 6: http://en.cppreference.com/w/cpp/io/manip/setprecision Thus this code should output: "5.2\n1" [[Live Example](http://ideone.com/ibCqpx)] – Jonathan Mee Dec 18 '15 at 12:30
  • This is a small part of my code, the char stream and the double "5.2" are a result of some processing. The double I used for comparison is precisely 5.2. When I wanted it to be compared to the char stream "5.2" I got the above conclusion. I also ran the above code on ideone.com I got 5.2 and 1. I am using vc13 and windows machine – Shikhar Bhargava Dec 18 '15 at 13:07

2 Answers2

3

numeric_limits<double>::digits10 can be used to find the number of digits that are uniquely representable by a double.

I see you've tagged your question with Visual Studio. You can test this code on http://webcompiler.cloudapp.net/ to get Visual Studio's number of uniquely representable digits for a double:

#include <iostream>
#include <limits>

int main() { std::cout << std::numeric_limits<double>::digits10 << std::endl; }

This code will not output 2 it will output:

15

Which means that any double up to 14 decimal places will survive the round trip through a stringstream and still be equal to itself.


The above means that there is something you are not including in your example that is causing the round trip failure, or you are using non-standard source files that are not IEEE compliant. (For example I can do a live example on gcc that gives a contrary output to yours, and running the same code on Visual Studio disagrees with your output.)

Either way, for any uniquely representable double (like 5.2), you can ensure that round trip success through a stringstream by setting the precision. Precision is a sticky modifier, so you'll only need to set it once after stream construction. In your example you use stringstream stream so before you work with stream you'd need to set this modifier:

stream.precision(numeric_limits<double>::digits10 - 1);
Community
  • 1
  • 1
Jonathan Mee
  • 37,899
  • 23
  • 129
  • 288
0

You can use it like this in order to show the double number in the right way:

#include <iostream>
#include <string>
#include <sstream>
#include <iomanip>
#include <cmath>
#include <limits>
int main()
{
    char doubleStr[] = "5.2";
    double d = 0.0;
    std::stringstream stream (doubleStr);
    stream >> d;
    std::cout << std::setprecision(2)<<  d << std::endl;
    return 0;
}

http://cpp.sh/9lub

about comparing float point numbers you may look at this What is the most effective way for float and double comparison?

Community
  • 1
  • 1
Humam Helfawi
  • 19,566
  • 15
  • 85
  • 160