atof和stringstream产生不同的结果 [英] atof and stringstream produce different results
问题描述
我一直在研究将浮点数转换为人类可读格式并转换回来的问题.即一个字符串.我在使用stringstream时遇到了问题,发现atof产生了更好"的结果.
I have been looking into a problem whereby I am converting a float to a human readable format, and back. Namely a string. I have ran into issues using stringstream and found that atof produces "better" results.
注意,在这种情况下,我不会打印出数据,而是使用调试器来检索值:
Notice, I do not print out the data in this case, I used the debugger to retrieve the values:
const char *val = "73.31";
std::stringstream ss;
ss << val << '\0';
float floatVal = 0.0f;
ss >> floatVal; //VALUE IS 73.3100052
floatVal = atof(val); //VALUE IS 73.3099976
对此可能有一个合理的解释.如果有人能启发我,我将非常感激:).
There is probably a reasonable explanation to this. If anybody can enlighten me I'd be greatful :).
推荐答案
答案是基于OP使用MSVC的假设
atof
在读取浮点值方面确实比istream
更好.
atof
is indeed better in reading floating point values than 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
的转换:
The compiler even warns about the conversion from double
to float
this:
warning C4244: '=': conversion from 'double' to 'float', possible loss of data
我还找到了此页面:转换浮点类型
更新:
值73.3099975585938
似乎是double
值73.31
的正确float
解释.
The value 73.3099975585938
seems to be the correct float
interpretation of the double
value 73.31
.
更新:
istream>>(double&)
也可以正常工作:
Update:
istream>>(double&)
works correctly as well:
#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
使用scanf("%g")
之类的内容源
For arithmetic types istream::operator>>
uses num_get::get
.
num_get::get
should be using something like scanf("%g")
for float
source
但是:
#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
For me this looks like there might be a bug in Microsoft num_get
这篇关于atof和stringstream产生不同的结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!