atof和stringstream产生不同的结果 [英] atof and stringstream produce different results

查看:143
本文介绍了atof和stringstream产生不同的结果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在研究将浮点数转换为人类可读格式并转换回来的问题.即一个字符串.我在使用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

编译器甚至警告从doublefloat的转换:

The compiler even warns about the conversion from doubleto float this:

warning C4244: '=': conversion from 'double' to 'float', possible loss of data

我还找到了此页面:转换浮点类型

更新:

73.3099975585938似乎是double73.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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆