usar functions como c++ floating-point integer pow clamp

functions - pow c++ como usar



pow para valores integrales (2)

¿C ++ me proporciona algún tipo de solución en línea aquí?

No, no hay pow entero en la biblioteca estándar.

o estoy atrapado escribiendo mi propia función

Sí, tienes que escribir tu propia función. Tenga en cuenta que el ciclo de multiplicación que se muestra puede ser más lento que utilizar std::pow para implementar la función, especialmente porque también tiene una bifurcación y división en el ciclo:

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; }

Para un enfoque más genérico, es posible que desee considerar el flujo insuficiente también.

También hay otros algoritmos más rápidos (véase, por ejemplo, Exponentiation by squaing ) para la exponenciación de enteros que el lineal que mostró, pero no estoy seguro de si valdría la pena considerarlos a menos que trate con aritmética de precisión arbitraria, o un sistema integrado sin unidad de punto flotante

Necesito una versión de pow para enteros. Tengo 2 problemas que necesito resolver con pow :

  1. Si el resultado es más grande que mi tipo integral, necesito numeric_limits::max() a numeric_limits::max()
  2. Necesito poder lidiar con 41.99999 redondeando hasta 42, en lugar de hasta 41

¿C ++ me proporciona algún tipo de solución en línea aquí, o estoy atrapado escribiendo mi propia función?

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; }


Su código no se compiló; si es posible, primero verifique las compilaciones de su código, utilice su compilador o compruébelo primero en el explorador de compiladores.

Además, olvidaste tener en cuenta los valores negativos. Esa es una característica muy importante de los poderes integrales. El siguiente código es para el tipo int regular. Te dejaré explorar cómo podrías ampliarlo para otros tipos integrales.

#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; }

En la vida real, haría esta nota sobre el uso del piso, incluso en el caso integral.

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)); }