don*_*lmg 4 c++ floating-point floating-accuracy
在对转换后的字符串执行某些操作后,我遇到了双精度问题.
#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;
}
Run Code Online (Sandbox Code Playgroud)
对于作为字符串输入的所有数字,情况并非如此,因此错误不是常数.它只影响一些数字(34.38似乎是不变的).
此时,当我传入a = 34.38且i = 100时,它会返回此值:
char a -- 34.38
Val ----- 34.38
modified val --- 3438
FMOD ----- 4.54747e-13
Run Code Online (Sandbox Code Playgroud)
如果我将Val更改为浮点数,这将有效,因为精度较低,但我需要一个双精度数.
当我使用atof,sscanf和strtod而不是sstream时,这也是repro.
在C++中,将字符串正确转换为double的最佳方法是什么,并实际返回一个准确的值?
谢谢.
Pet*_*ham 11
这几乎是这里很多问题的完全重复 - 基本上没有二进制浮点的34.38的精确表示,所以你的34 + 19/50表示为34 + k/n,其中n是2的幂,并且没有两个具有50作为因子的精确幂,因此没有确切的k值可能.
如果设置输出精度,则可以看到最佳双精度表示不精确:
cout << fixed << setprecision ( 20 );
Run Code Online (Sandbox Code Playgroud)
给
char a -- 34.38
val ----- 34.38000000000000255795
modified val --- 3438.00000000000045474735
FMOD ----- 0.00000000000045474735
Run Code Online (Sandbox Code Playgroud)
所以在回答你的问题时,你已经在使用最好的方法将字符串转换为double(虽然boost lexical cast将你的两行或三行包装成一行,所以可能会节省你编写自己的函数).结果是由于双精度使用的表示,并且将适用于基于二进制浮点的任何有限表示.
对于浮点数,乘法恰好是向下舍入而不是向上,所以你碰巧得到了一个确切的结果.这不是您可以依赖的行为.