C ++ Precision: String to Double

I have a problem accurate to double after doing some operations on the converted string to double.

#include <iostream> #include <sstream> #include <math.h> using namespace std; // conversion function void convert(const char * a, const int i, double &out) { double val; istringstream in(a); in >> val; cout << "char a -- " << a << endl; cout << "val ----- " << val << endl; val *= i; cout << "modified val --- " << val << endl; cout << "FMOD ----- " << fmod(val, 1) << endl; out = val; return 0; } 

This does not apply to all numbers entered as a string, so the error is not constant. This only affects some numbers (34.38 seems constant).

In a minute, this returns this when I pass a = 34.38 and I = 100:

 char a -- 34.38 Val ----- 34.38 modified val --- 3438 FMOD ----- 4.54747e-13 

This will work if I change Val to float, as there is lower precision, but I need double.

This also plays when I use atof, sscanf and strtod instead of sstream.

In C ++, what is the best way to correctly convert a string to double and actually return the exact value?

Thanks.

+4
source share
2 answers

This is an almost exact duplicate of many questions here - basically there is no exact representation of 34.38 in binary floating point, so your 34 + 19/50 is represented as 34 + k / n, where n is the power of two, and there is no exact power of two that has 50 as a factor, therefore there is no exact value of k.

If you set the output precision, you will see that the best double view is not accurate:

 cout << fixed << setprecision ( 20 ); 

gives

 char a -- 34.38 val ----- 34.38000000000000255795 modified val --- 3438.00000000000045474735 FMOD ----- 0.00000000000045474735 

So, in response to your question, you are already using the best way to convert a string to double (although boost lexical cast completes your two or three lines in one line, so you can write your own function). The result is explained by the representation used by the doubles, and will apply to any final representation based on a binary floating point.

With floats, the multiplication is rounded, not up, so you get the exact result. This is not behavior you can rely on.

+11
source

The β€œproblem” here is simply that 34.38 cannot be represented exactly with double precision floating point. You should read this article , which describes why it is not possible to represent decimal values ​​exactly in a floating point.

If you were to learn "34.38 * 100" in hexadecimal format (for example, in the "hex" format in MATLAB), you will see:

 40aadc0000000001 

Pay attention to the final figure.

+1
source

Source: https://habr.com/ru/post/1315053/


All Articles