【问题标题】:C++, scientific notation, format numberC++、科学计数法、格式号
【发布时间】:2011-10-31 06:28:09
【问题描述】:

是否可以通过以下方式以科学计数法格式化字符串:

  • 在指数中设置固定位置:1

  • 在尾数中设置固定小数位:0

     double number = 123456.789
    

所以数字应该是格式化的

  1e+5

我无法为尾数设置 0 个小数点:

cout.precision(0);
cout << scientific << number;

结果:

1.234568e+005

【问题讨论】:

  • 当然可以。您想要代码还是正在寻找一种使用标准字符串格式化库/工具的方法?
  • 一些代码对他有帮助.. :-)

标签: c++ format scientific-notation


【解决方案1】:

我不知道如何在指数字段中获取单个数字,但以下内容符合您的所有其他要求。

#include <iostream>
#include <iomanip>

int main()
{
  const double number = 123456.789;

  std::cout << std::setprecision(0) << std::scientific << number << std::endl;
}

输出:

1e+05

编辑:
快速搜索了标准(N3291),在使用科学记数法时找不到任何关于指数字段中位数的内容。这可能是实现定义的。

【讨论】:

  • 在 VS2010 下,如果给我的结果与我的代码相同:1.234568e+005
【解决方案2】:

您可以使用{fmt} formatting library 轻松做到这一点:

#include <fmt/core.h>

double number = 123456.789;
auto s = fmt::format("{:.0e}\n", number); // s == "1e+05"
s.erase(s.size() - 2, 1); // s == "1e+5"

基于此库的格式化工具被提议用于 C++20 中的标准化:P0645

免责声明:我是 {fmt} 的作者。

【讨论】:

    【解决方案3】:

    我不确定您使用的是哪个 C++ 编译器,它会为您提供 3 位指数——C 和 C++ 标准要求至少 2 位数字,而 g++ 就是这样做的。使用标准 C 或 C++ I/O 函数无法只获得一位数,因此您必须推出自己的解决方案。由于进行浮点到字符串的转换是a very tricky problem [PDF],我强烈建议不要这样做,而是对结果进行后处理。

    这是一种方法:

    // C version; you can rewrite this to use std::string in C++ if you want
    void my_print_scientific(char *dest, size_t size, double value)
    {
        // First print out using scientific notation with 0 mantissa digits
        snprintf(dest, size, "%.0e", value);
    
        // Find the exponent and skip the "e" and the sign
        char *exponent = strchr(dest, 'e') + 2;
    
        // If we have an exponent starting with 0, drop it
        if(exponent != NULL && exponent[0] == '0')
        {
            exponent[0] = exponent[1];
            exponent[1] = '\0';
        }
    }
    

    【讨论】:

      【解决方案4】:

      一旦你有一个字符串,你实际上可以格式化任何东西。更多的 c++ 代码看起来像:

      const double number = 123456.789;
      const int expSize = 1;
      std::ostringstream oss;
      std::string output;
      oss << std::scientific << number;
      unsigned int ePos = oss.str().find("e");
      unsigned int dPos = oss.str().find(".");
      if(ePos == 0){
          //no exponent
      }
      else if(dPos == 0){
          //not decimal
      }
      else{
          output = oss.str().substr(0, dPos) + oss.str().substr(ePos, 2);
          if(oss.str().size()-expSize > ePos+1)
              output += oss.str().substr(oss.str().size()-expSize, oss.str().size());
          else{
              //expSize too big (or bug -> e used but no exponent?)
          }
          std::cout << output;
      }
      

      输出:

      1e+5
      

      您可以在 expSize 中设置指数大小,这适用于任意大指数。

      希望对你有帮助!

      【讨论】:

        【解决方案5】:

        这是一个流解决方案:

        #include <iostream>
        #include <iomanip>
        using namespace std;
        
        template<typename T>
        struct scientificNumberType
        {
            explicit scientificNumberType(T number, int decimalPlaces) : number(number), decimalPlaces(decimalPlaces) {}
        
            T number;
            int decimalPlaces;
        };
        
        template<typename T>
        scientificNumberType<T> scientificNumber(T t, int decimalPlaces)
        {
            return scientificNumberType<T>(t, decimalPlaces);
        }
        
        template<typename T>
        std::ostream& operator<<(std::ostream& os, const scientificNumberType<T>& n)
        {
            double numberDouble = n.number;
        
            int eToThe = 0;
            for(; numberDouble > 9; ++eToThe)
            {
                numberDouble /= 10;
            }
        
            // memorize old state
            std::ios oldState(nullptr);
            oldState.copyfmt(os);
        
            os << std::fixed << std::setprecision(n.decimalPlaces) << numberDouble << "e" << eToThe;
        
            // restore state
            os.copyfmt(oldState);
        
            return os;
        }
        

        使用示例:

        int main()
        {
            double e = 1.234;
        
            cout << scientificNumber(e, 1) << " " << scientificNumber(e, 3);
        
            return 0;
        }
        

        输出: 1.2e0 1.234e0

        【讨论】:

          猜你喜欢
          • 2021-12-22
          • 2022-12-21
          • 1970-01-01
          • 2013-08-06
          • 1970-01-01
          • 1970-01-01
          • 2017-02-08
          • 2011-02-26
          • 1970-01-01
          相关资源
          最近更新 更多