round函数 - c++ sqrt




pow为整体值 (2)

我需要一个整数的pow版本。 我有2个问题,我需要解决pow

  1. 如果结果大于我的整数类型,我需要钳制到numeric_limits::max()
  2. 我需要能够处理41.99999四舍五入到42,而不是41

C ++是否为我提供了某种内联解决方案,或者我写了自己的函数:

template <typename T>
enable_if_t<is_integral_v<T>, T> mypow(const T base, unsigned int exp) {
    T result = exp == 0U ? base : 1;

    while(exp-- > 1U) {
        if(numeric_limits<T>::max() / result <= base) return numeric_limits<T>::max();
        result *= base;
    }
    return result;
}

C ++是否为我提供了某种内联解决方案

不,标准库中没有整数pow

还是我坚持写我自己的功能

是的,你可以写自己的功能。 请注意,显示的乘法循环可能比使用std::pow来实现该函数要慢,特别是因为在循环中也有一个分支和除法:

template<class I>
I int_pow_no_overflow(I base, I exp)
{
    double max = std::numeric_limits<I>::max();
    double result = std::round(std::pow(base, exp));
    return result >= max
        ? max
        : result;
}

对于更通用的方法,您可能也要考虑下溢。

对于整数幂运算,还有其他更快的算法(例如按平方求幂),但是我不确定是否值得考虑它们,除非处理任意精度算法或嵌入式系统没有浮点单元。


你的代码没有编译,你应该尽可能先检查你的代码编译,使用你的编译器,或者先在编译器资源管理器上检查它。

另外,你忘了考虑负面的价值。 这是整体力量的一个非常重要的特征。 下面的代码是用于普通的int类型。 我会让你探索如何扩展它为其他整型。

#include <type_traits>
#include <iostream>
#include <cmath>
#include <limits>

using namespace std;

template <typename T>
enable_if_t< is_integral<T>::value, T> 
mypow(T base, unsigned int exp) 
{
    T result = T(1);
    bool sign = (base < 0);

    if (sign) base = -base;

    T temp = result;
    while(exp-- != 0) 
    {
        temp *= base;
        if (temp < result)
        {
            return (sign) ? numeric_limits<T>::min() 
                          : numeric_limits<T>::max();
        }
        result = temp;
    }
    return (sign && (exp & 1)) ? -result : result;
}

template <typename T>
enable_if_t< !is_integral<T>::value, int> 
mypow(const T& base, unsigned int exp) 
{
    T result = T(1);
    int i_base = int(floor(base + .5));
    bool sign = (i_base < 0);

    if (sign) i_base = -i_base;

    int temp = result;
    while(exp-- != 0) 
    {
        temp *= i_base;
        if (temp < result)
        {
            return (sign) ? numeric_limits<int>::min() : numeric_limits<int>::max();
        }
        result = temp;
    }
    return (sign && (exp & 1)) ? -result : result;
}

在现实生活中,即使在整体情况下,我也会这样做。

  template<typename T>
   enable_if_t< is_integral<T>::value, T> 
   mypow(T x, unsigned int y) { return T(floor(pow(x, y) + .5)); }

   template<typename T>
   enable_if_t< !is_integral<T>::value, int> 
   mypow(T x, unsigned int y) { return int(floor(pow(floor(x + .5), y) + .5)); }




clamp