gpt4 book ai didi

c++ - 如何让所有平台编译器为 NaN 输出相同的字符串?

转载 作者:可可西里 更新时间:2023-11-01 17:39:01 25 4
gpt4 key购买 nike

考虑这个代码片段:

#include <iostream>
#include <string>
#include <limits>

int main()
{
std::cout << std::numeric_limits<double>::quiet_NaN();
}

使用 Visual Studio 2010 编译时,输出为 1.#QNAN .使用 g++ 编译时,输出为 nan .请注意,Visual Studio 2015 输出“nan”。

但是,我需要两者来产生相同的输出。最简单的方法是什么?我试图覆盖 operator<<对于 double但我觉得那不是正确的做法。可以将字符串用于 NaN值被强制为 stream级别,或更好,在全局级别(使用 std::locale 东西?...从未使用过...)。

我找到了这个 squaring_num_put例子。有趣的是,它是一种将修改数字重定向到输出的方法。但是我很难让它适应我的问题(无法使 do_put 将数字或硬编码的“NaN”字符串发送到 ostream ...)。

最佳答案

您可以使用流操纵器或修改底层语言环境:

操纵器:

#include <cmath>
#include <ostream>

template <typename T>
struct FloatFormat
{
const T value;

FloatFormat(const T& value)
: value(value)
{}

void write(std::ostream& stream) const {
if(std::isnan(value))
stream << "Not a Number";
else
stream << value;
}
};

template <typename T>
inline FloatFormat<T> float_format(const T& value) {
return FloatFormat<T>(value);
}

template <typename T>
inline std::ostream& operator << (std::ostream& stream, const FloatFormat<T>& value) {
value.write(stream);
return stream;
}

int main() {
std::cout << float_format(std::numeric_limits<double>::quiet_NaN()) << '\n';

}

语言环境:

#include <cmath>
#include <locale>
#include <ostream>

template<typename Iterator = std::ostreambuf_iterator<char>>
class NumPut : public std::num_put<char, Iterator>
{
private:
using base_type = std::num_put<char, Iterator>;

public:
using char_type = typename base_type::char_type;
using iter_type = typename base_type::iter_type;

NumPut(std::size_t refs = 0)
: base_type(refs)
{}

protected:
virtual iter_type do_put(iter_type out, std::ios_base& str, char_type fill, double v) const override {
if(std::isnan(v))
out = std::copy(std::begin(NotANumber), std::end(NotANumber), out);
else
out = base_type::do_put(out, str, fill, v);
return out;
}

virtual iter_type do_put(iter_type out, std::ios_base& str, char_type fill, long double v) const override {
if(std::isnan(v))
out = std::copy(std::begin(NotANumber), std::end(NotANumber), out);
else
out = base_type::do_put(out, str, fill, v);
return out;
}

private:
static const char NotANumber[];
};

template<typename Iterator>
const char NumPut<Iterator>::NotANumber[] = "Not a Number";

#include <iostream>
#include <limits>

int main() {
#if 1
{
const std::size_t NoDestroy = 1;
NumPut<> num_put(NoDestroy);
std::locale locale(std::cout.getloc(), &num_put);
std::locale restore_locale = std::cin.getloc();
std::cout.imbue(locale);
std::cout << std::numeric_limits<double>::quiet_NaN() << '\n';
// The num_put facet is going out of scope:
std::cout.imbue(restore_locale);
}
#else
{
// Alternitvely use a reference counted facet and pass the ownership to the locales:
auto num_put = new NumPut<>();
std::locale locale(std::cout.getloc(), num_put);
std::cout.imbue(locale);
std::cout << std::numeric_limits<double>::quiet_NaN() << '\n';
}
#endif
std::cout << std::numeric_limits<double>::quiet_NaN() << '\n';
}

关于c++ - 如何让所有平台编译器为 NaN 输出相同的字符串?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35270826/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com