double和stringstream格式

时间:2012-10-15 11:37:28

标签: c++ double

double val = 0.1;
std::stringstream ss;
ss << val;
std::string strVal= ss.str();

在Visual Studio调试器中,val的值为0.10000000000000001(因为无法表示0.1)。 使用字符串流转换val时,strVal等于"0.1"。但是,使用boost :: lexical_cast时,生成的strVal"0.10000000000000001"

另一个例子如下:

double val = 12.12305000012;

在visual studio val下显示为12.123050000119999,并使用stringstream和默认精度(6),它变为12.1231。我真的不明白为什么它不是12.12305(...)。

是否存在默认精度,或者stringstream是否有特定的算法来转换无法准确表示的double值?

感谢。

4 个答案:

答案 0 :(得分:12)

您可以按如下方式更改stringstream的浮点精度:

double num = 2.25149;
std::stringstream ss(stringstream::in | stringstream::out);
ss << std::setprecision(5) << num << endl;
ss << std::setprecision(4) << num << endl;

输出:

2.2515
2.251

注意在适当的时候数字也是如何舍入的。

答案 1 :(得分:11)

对于任何获得&#34; error: ‘setprecision’ is not a member of ‘std’&#34;您必须#include <iomanip>其他setprecision(17)无效!

答案 2 :(得分:4)

问题出现在流插入ss << 0.1;而不是转换为字符串。如果需要非默认精度,则需要在插入double之前指定它:

ss << std::setprecision(17) << val;

在我的计算机上,如果我只使用setprecision(16),我仍然会"0.1"而不是"0.10000000000000001"。我需要一个(略微虚假)精度为17才能看到最后的1。

<强>附录
更好的演示产生的值为1.0 / 3.0。使用默认精度,您将获得"0.333333"的字符串表示形式。这不是相当于双精度1/3的字符串。使用setprecision(16)生成字符串"0.3333333333333333";精度为17会产生"0.33333333333333331"

答案 3 :(得分:3)

您必须考虑两个问题。首先是精度 参数,默认为6(但你可以设置为任何你 喜欢)。第二个是这个参数的含义,这取决于 您正在使用的格式选项:如果您使用固定或科学 格式,则表示小数点后的位数(以in为单位) 转弯对精确度通常意味着什么产生不同的影响 两种格式);但是,如果您使用的是默认精度(ss.setf( std::ios_base::fmtflags(), std::ios_base::formatfield ),则表示 输出中的位数,无论输出是否为 实际上使用科学或固定的表示法格式化。这解释了 为什么你的显示是12.1231,例如;你正在使用两者 默认精度和默认格式。

您可能希望尝试以下不同的值(也许 不同的精度):

std::cout.setf( std::ios_base::fmtflags(), std::ios_base::floatfield );
std::cout << "default:    " << value[i] << std::endl;
std::cout.setf( std::ios_base::fixed, std::ios_base::floatfield );
std::cout << "fixed:      " << value[i] << std::endl;
std::cout.setf( std::ios_base::scientific, std::ios_base::floatfield );
std::cout << "scientific: " << value[i] << std::endl;

看到实际输出可能比任何详细描述更清晰:

default:    0.1
fixed:      0.100000
scientific: 1.000000e-01