双重和字符串流格式
double and stringstream formatting
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.12305000011999,使用字符串流和默认精度(6),它变为12.1231。我真的不明白为什么不是12.12305(…)。
是否有默认精度,或者字符串流是否有特定的算法来转换无法精确表示的双值?
谢谢。
您可以更改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
请注意,在适当的情况下,数字也是四舍五入的。
对于任何获得"error: ‘setprecision’ is not a member of ‘std’
"的人,您必须使用#include <iomanip>
,否则setprecision(17)
将不起作用!
您必须考虑两个问题。第一是精度参数,默认为6(但您可以将其设置为类似)。第二个是这个参数的含义,这取决于您正在使用的格式选项:如果您使用的是固定格式或科学格式格式,则表示小数后的位数(在转弯对两种格式);但是,如果使用默认精度(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
问题发生在流插入ss << 0.1;
,而不是转换为字符串。如果你想要非默认精度,你需要在插入双精度之前指定:
ss << std::setprecision(17) << val;
在我的电脑上,如果我只使用setprecision(16)
,我仍然会得到"0.1"
,而不是"0.10000000000000001"
。我需要一个(稍微伪造的)17的精度才能看到最后的1。
附录
如果值为1.0/3.0,则会出现更好的演示。使用默认精度,可以得到"0.333333"
的字符串表示。这不是相当于双精度1/3的字符串。使用CCD_ 20使得字符串CCD_;精度为17得到CCD_ 22。
- 是否可以从格式字符串中检索"width"
- 我应该如何从 stdin C++ 中读取可变长度的格式字符串?
- 从用户定义的类生成格式字符串?
- 如何连接格式字符串?
- 如何在C++中将"%Y%m%d"格式字符串转换为time_t变量?
- CPPCHECK C++成员函数上的格式字符串
- scanf() 语句中"%*[^n]"的格式字符串指示什么?分配抑制器 (*) 和否定扫描集 ([^) 如何协同工作?
- 自定义 {fmt} 格式化函数,具有编译时格式字符串检查功能
- '|' scanf 格式字符串是什么意思
- 如何使用 msgfmt 验证格式字符串中的位置表示法占位符
- sscanf_s:格式字符串"%d"需要类型为"int *"的参数,但可变参数 4 的类型为"WORD *"
- C4477: 'fprintf' :格式字符串 '%s' 需要类型为"char *"的参数,但可变参数 1 的类型为"int *"
- 如何使用OpenSSL API从其PEM格式字符串中读取RSA公钥
- C 格式字符串宏
- C++等效于 C 的格式字符串
- 如何使用 C++ 中的 rapidjson 库从 json 格式字符串中获取值
- _vsnprintf和_vsnprintf_s的格式字符串中的可用百分比字符
- 如何将格式字符串发送到iostream
- 跨平台格式字符串
- 使用 swprintf() 打印"0x0"的格式字符串应该是什么?