如何格式化浮点值,使其从不使用指数表示法,也不具有尾随零?

bit*_*ask 8 c++ floating-point iostream string-formatting

的ios_base操纵,我基本上之间的选择defaultfloatfixed不带指数的符号格式浮点数时(有小数).

但是,我想选择最大精度,它会为许多数字产生很多尾随零fixed(例如1.),但避免使用指数表示法.如果设置为defaultfloat,它将在大多数时间看起来正确,除非值非常小,但不是0..在这种情况下,默认表示单独切换到科学记数法,这打破了格式化输出的接收者(因为它不知道是什么2.22045e-16意思.

那么,我怎么能吃馅饼呢?也就是说,没有不必要的尾随零的非指数表示法.


注意:我没有测试defaultfloat标志的效果,因为我的gcc似乎没有实现那个标志(但是),但我认为它是默认设置,适用时不使用任何标志.我确实检查了fixed标志,它确实按预期运行.

bit*_*ask 1

由于似乎没有正确的方法来使用 stdlib 执行此操作,因此这是我的包装器。

  template <typename T>
  struct FpFormat {
    template <typename Stream>
    static Stream& setfmt(Stream& str) {
      return str;
    }
    template <typename String>
    static String const& untrail(String const& str) {
      return str;
    }
  };
  template <typename T>
  struct FpFormatFloats {
    template <typename Stream>
    static auto setfmt(Stream& str) -> decltype(str << std::fixed << std::setprecision(std::numeric_limits<T>::digits10)) {
      return str << std::fixed << std::setprecision(std::numeric_limits<T>::digits10);
    }
    template <typename String>
    static String untrail(String str) {
      if (str.find('.') == String::npos)
        return str;
      return ([](String s){
        return String(s.begin(),s.begin()+((s.back() == '.')?(s.size()-1):s.size()));
      })(str.substr(0,(str+"0").find_last_not_of('0')+1));
    }
  };
  template <> struct FpFormat<float> : FpFormatFloats<float> {};
  template <> struct FpFormat<double> : FpFormatFloats<double> {};
  template <> struct FpFormat<long double> : FpFormatFloats<long double> {};

  template <typename T>
  std::string toString(T x) {
    std::stringstream str;
    FpFormat<T>::setfmt(str) << x;
    return FpFormat<T>::untrail(str.str());
  }
Run Code Online (Sandbox Code Playgroud)