atof 和 stringstream 产生不同的结果
atof and stringstream produce different results
我一直在研究将浮点数转换为人类可读格式并返回的问题。即一个字符串。我 运行 使用 stringstream 遇到问题,发现 atof 产生 "better" 结果。
注意,在这种情况下我没有打印出数据,我使用调试器检索值:
const char *val = "73.31";
std::stringstream ss;
ss << val << '[=10=]';
float floatVal = 0.0f;
ss >> floatVal; //VALUE IS 73.3100052
floatVal = atof(val); //VALUE IS 73.3099976
对此可能有一个合理的解释。如果有人能启发我,我将不胜感激:)。
答案是基于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
我还找到了这个页面:Conversions from Floating-Point Types
更新:
值 73.3099975585938
似乎是对 double
值 73.31
的正确 float
解释。
更新:
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
。
num_get::get
应该为 float
source
使用类似 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
我一直在研究将浮点数转换为人类可读格式并返回的问题。即一个字符串。我 运行 使用 stringstream 遇到问题,发现 atof 产生 "better" 结果。
注意,在这种情况下我没有打印出数据,我使用调试器检索值:
const char *val = "73.31";
std::stringstream ss;
ss << val << '[=10=]';
float floatVal = 0.0f;
ss >> floatVal; //VALUE IS 73.3100052
floatVal = atof(val); //VALUE IS 73.3099976
对此可能有一个合理的解释。如果有人能启发我,我将不胜感激:)。
答案是基于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
我还找到了这个页面:Conversions from Floating-Point Types
更新:
值 73.3099975585938
似乎是对 double
值 73.31
的正确 float
解释。
更新:
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
。
num_get::get
应该为 float
source
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