std::p ow() 输出是..特殊

std::pow() output is... special?

本文关键字:输出 特殊 ow std      更新时间:2023-10-16

嘿,希望所有这些都是一个简单的问题,但这对我来说是全新的,我不知道为什么会发生这种情况。采用以下C++代码:

template<class T>
T expo(T a, T b){
    T result = 1;
    while(b) {
        if(b & 1)result *= a;
        b >>=1 ;
        a *= a;
    }
    return result;
}
int main() {
    cout << std::pow<size_t>(50, 5) << endl;
    cout << expo<size_t>(50, 5) << endl;
}

输出为:

3.125e+008
312500000

两者都是正确的,但std::pow()将输出格式化为科学记数法。它到底是怎么做到的?一定有我一直缺少C++的特征。帮助!

无论

输入的类型是什么,pow的返回类型都是double/float的,expo的返回类型是size_t的,因为编译器为size_t实例化expo。您可以使用std::fixed将双精度格式设置为非科学格式。

重要更新:

gcc 中有一个用于 pow 的模板基声明(我不确定它是否标准),它接受类型:

  template<typename _Tp, typename _Up>
    inline typename __gnu_cxx::__promote_2<_Tp, _Up>::__type
    pow(_Tp __x, _Up __y)
    {
      typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type;
      return std::pow(__type(__x), __type(__y));
    }

返回值为 double/float

所以基本的答案是:

std::pow<size_t>(50, 5)

返回双精度,因此输出默认为科学格式。如果我们查看有关 cppreference 的文档,它声称自 C++11 *积分* 参数被转换为双倍,并且这些情况的输出应该是双倍我很难从标准中固定出如此强烈的声明,但输出与该解释一致。

我们可以确认输出确实至少doublegcc 次,并且使用 std::typeid clang

std::cout << typeid( std::pow<size_t>(50, 5)).name() << std::endl;

当我们运行该输出时d哪个输出c++filt -t d它告诉我们它是双倍的。

更新

在C++标准草案中找到了相关部分。如果我们查看第 26 节 Numerics 库,然后转到涵盖 <cmath> 标头的第 26.8 C 库部分,它指定了8 段中涵盖的浮点数、双精度数和长双精度数的数学函数的重载:

除了 中数学函数的双重版本之外,C++还添加了这些函数的浮点数和长双重载版本,具有相同的语义。

它涵盖了第11段中的整体情况,其中说(强调我的):

此外,还应有额外的超载,足以确保:

    如果对应于双精度参数的任何算术参数具有长双精度
  1. 类型,则对应于双精度参数的所有算术参数都将有效地转换为长双精度。
  2. 否则,如果对应于双精度参数的任何算术参数
  3. 具有双精度类型或整数类型,则对应于双精度参数的所有算术参数都将有效地转换为双精度。
  4. 否则,对应于双精度参数的所有算术参数都具有浮点类型。