3

嘿,这一切希望是一个简单的问题来回答,但这对我来说是全新的,我不知道为什么会这样。采用以下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++特性。帮助!

4

2 回答 2

3

的返回类型与输入的类型无关,而 的返回类型pow是因为编译器实例化了for 。您可以使用使双重格式变得不科学。double/floatexposize_texposize_tstd::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

于 2013-10-22T13:10:58.617 回答
1

所以基本的答案是:

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

正在返回一个精度,因此输出默认为科学格式。如果我们查看有关cppreference的文档, 它声称C++11 *integral* 参数被强制转换为double并且这些情况的输出应该是double。我无法从标准中确定一个强有力的声明,但输出与该解释一致。

我们可以确认输出确实double是至少gcc并且clang使用std::typeid

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

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

更新

在C++ 标准草案中找到了相关部分。如果我们查看26 Numerics 库部分,然后转到包含标题的 C 部分库26.8 它指定了第8段中涵盖的floatdoublelong double<cmath>的数学函数的重载:

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

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

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

  1. 如果对应于 double 参数的任何算术参数的类型为 long double,则对应于 double 参数的所有算术参数都将有效地强制转换为 long double。
  2. 否则,如果对应于 double 参数的任何算术参数具有 double 类型或整数类型,则对应于 double 参数的所有算术参数都将有效地转换为 double。
  3. 否则,对应于双参数的所有算术参数都具有浮点类型。
于 2013-10-22T13:47:16.000 回答