回答基于 OP 使用 MSVC 的假设
atof
在读取浮点数方面确实比 istream
更好。
以下是一个例子:
#include <iostream>
#include <sstream>
#include <iomanip>
#include <cstdlib>
int main()
{
const char *val = "73.31";
std::stringstream ss;
ss << val;
float floatVal = 0.0f;
ss >> floatVal;
std::cout << "istream>>(float&) :" << std::setw(18) << std::setprecision(15) << floatVal << std::endl;
double doubleVal = atof(val);
std::cout << "double atof(const char*) :" << std::setw(18) << std::setprecision(15) << doubleVal << std::endl;
floatVal = doubleVal;
std::cout << "(float)double atof(const char*) :" << std::setw(18) << std::setprecision(15) << floatVal << std::endl;
doubleVal = floatVal;
std::cout << "(double)(float)double atof(const char*) :" << std::setw(18) << std::setprecision(15) << floatVal << std::endl;
}
输出:
istream>>(float&) : 73.3100051879883
double atof(const char*) : 73.31
(float)double atof(const char*) : 73.3099975585938
(double)(float)double atof(const char*) : 73.3099975585938
编译器甚至会警告这种从
double
转换为
float
的情况:
warning C4244: '=': conversion from 'double' to 'float', possible loss of data
我还找到了这个页面:浮点类型的转换
更新:
数值 73.3099975585938
似乎是正确的 float
解释 double
数值 73.31
。
更新:istream>>(double&)
同样可以正常工作:
#include <iostream>
#include <sstream>
#include <iomanip>
#include <cstdlib>
int main()
{
const char *val = "73.31";
std::stringstream ss;
ss << val;
double doubleVal = 0.0f;
ss >> doubleVal;
std::cout << "istream>>(double&) :" << std::setw(18) << std::setprecision(15) << doubleVal << std::endl;
}
输出:
istream>>(double&) : 73.31
对于算术类型,istream::operator>>
使用 num_get::get
。对于 float
,num_get::get
应该使用类似于 scanf("%g")
的东西。(来源)
但是:
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string>
#include <iomanip>
#include <cstdlib>
int main()
{
std::string s = "73.31";
float f = 0.f;
sscanf(s.c_str(), "%g", &f);
std::cout << std::setw(18) << std::setprecision(15) << f << std::endl;
}
输出:
73.3099975585938
对我来说,这似乎是Microsoft的num_get
存在漏洞。
<< '\0'
是多余的。 - emlai73.3100051879883
,73.3099975585938
。 - Simon Kraemer