【发布时间】:2011-11-20 15:14:56
【问题描述】:
我想使用 iostream 和 Visual C++ 在文本文件中读取和写入 NaN 值。写入 NaN 值时,我得到1.#QNAN。但是,读回来输出1.0。
float nan = std::numeric_limits<float>::quiet_NaN ();
std::ofstream os("output.txt");
os << nan ;
os.close();
输出为1.#QNAN。
std::ifstream is("output.txt");
is >> nan ;
is.close();
nan 等于 1.0。
解决方案
最后,按照 awoodland 的建议,我想出了这个解决方案。我选择“nan”作为 NaN 的字符串表示。 > 运算符都被覆盖。
using namespace ::std;
class NaNStream
{
public:
NaNStream(ostream& _out, istream& _in):out(_out), in(_in){}
template<typename T>
const NaNStream& operator<<(const T& v) const {out << v;return *this;}
template<typename T>
const NaNStream& operator>>(T& v) const {in >> v;return *this;}
protected:
ostream& out;
istream& in;
};
// override << operator for float type
template <> const NaNStream& NaNStream::operator<<(const float& v) const
{
// test whether v is NaN
if( v == v )
out << v;
else
out << "nan";
return *this;
}
// override >> operator for float type
template <> const NaNStream& NaNStream::operator>>(float& v) const
{
if (in >> v)
return *this;
in.clear();
std::string str;
if (!(in >> str))
return *this;
if (str == "nan")
v = std::numeric_limits<float>::quiet_NaN();
else
in.setstate(std::ios::badbit); // Whoops, we've still "stolen" the string
return *this;
}
一个最小的工作示例:一个有限浮点数和一个 NaN 被写入一个字符串流,然后读回。
int main(int,char**)
{
std::stringstream ss;
NaNStream nis(ss, ss);
nis << 1.5f << std::numeric_limits<float>::quiet_NaN ();
std::cout << ss.str() << std::endl; // OUTPUT : "1.5nan"
float a, b;
nis >> a; nis >> b;
std::cout << a << b << std::endl; // OUTPUT : "1.51.#QNAN"
}
【问题讨论】:
-
问题应该是“如何使用 NaN 进行格式化 I/O”。我想。好问题。
-
pubs.opengroup.org/onlinepubs/007904975/functions/scanf.html 说
If the fprintf() family of functions generates character string representations for infinity and NaN (a symbolic entity encoded in floating-point format) to support IEEE Std 754-1985, the fscanf() family of functions shall recognize them as input.不惜一切代价。 -
@Moo:如果这是真的,那么至少我们现在知道 iostreams 不使用
fscanf:-) 无论如何,这都是一件可笑的事情,因为文本NaN 的表示因编译器而异,也可能因州而异。也许只是不可能读取 NaN。 (甚至连字面意思都没有,想起来了。) -
@KerrekSB:
"NaN"_my_super_duper_literal_operator:P -
@Mooing Duck:请注意,文档引用了 C99 标准(又名 ISO/IEC 9899:1999),正如我在回答中提到的,微软的运行时不符合该标准。
标签: c++ visual-c++ floating-point iostream