std :: pow()输出是......特别的?

时间:2013-10-22 13:08:42

标签: c++ templates format pow

嘿,所有这些希望是一个简单的问题要回答,但这对我来说是全新的,我不知道它为什么会发生。使用以下 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 ++ 的功能。救命啊!

2 个答案:

答案 0 :(得分:3)

pow的返回类型是double/float,无论输入的类型是什么,expo的返回类型是size_t,因为编译器实例化了expo } size_t。 您可以使用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

答案 1 :(得分:1)

所以基本答案是:

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

返回 double ,因此输出默认为 scientific 格式。如果我们查看 cppreference it claims上的文档,那么 C ++ 11 * integral *参数将转换为 double 和这些情况的输出应为 double 。我无法将标准中强烈的声明固定,但输出与该解释一致。

我们可以使用std::typeid确认至少doublegcc的输出确实为clang

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

当我们通过d运行时输出c++filt -t d,它告诉我们它是 double

更新

找到draft C++ standard中的相关部分。如果我们查看26 Numerics库部分,然后转到涵盖26.8标题的<cmath> C库部分,它会指定 float double long double 的数学函数的重载,其中包含 8

  

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

它涵盖 11 段落中的整数案例,其中说明了(强调我的):

  

此外,还应有足够的额外过载来确保:

     
    
        
  1. 如果对应于double参数的任何算术参数的类型为long double,则对应于double参数的所有算术参数都有效地转换为long double。
  2.     
  3. 否则,如果对应于double参数的任何算术参数具有double类型或整数类型,则则对应于double参数的所有算术参数将被有效地转换为double。
  4.     
  5. 否则,与double参数对应的所有算术参数都具有float。
  6. 类型