¿Existe una alternativa no flotante a pow ()?

9

He buscado la REFERENCIA DE IDIOMA en el sitio web de Arduino , y no puedo encontrar un equivalente que no sea flotante, pow() me falta algo grande, ¡pero por mi vida, estoy perplejo! Encontré pow()en la columna FUNCIONES bajo el encabezado Matemáticas (como era de esperar), pero dice que ambos parámetros, [base] y [exponente] son ​​ambos (flotante). Y solo hay otras seis entradas bajo el encabezado Math; ninguno de ellos parece ser una versión entera. Todo lo que quiero hacer es generar las potencias de 2 usando los exponentes de 0 a 10. Como 2 ^ 0 = 1 luego 2 ^ 1 = 2 luego 2 ^ 2 = 4 luego 2 ^ 3 = 8 luego 2 ^ 4 = 16 luego 2 ^ 5 = 32 luego 2 ^ 6 = 64 luego 2 ^ 7 = 128 luego 2 ^ 8 = 256 luego 2 ^ 9 = 512 luego 2 ^ 10 es 1024

¿Usar flotadores es la única forma en que puedo hacer esto? Estoy empezando a sentir que estoy en desacuerdo con la realidad, y de hecho he contado mi medicamento, pero estoy justo donde debería estar. Permítanme disculparme de antemano por este descuido atroz con el que he perdido su tiempo, pero he revisado las 9 páginas de etiquetas y he hecho alguna búsqueda en la que pueda pensar. ¡Admitiré que no he pasado tanto tiempo, pero estaba seguro de que esto solo sería como una cosa de cinco minutos!

Bence Kaulics
fuente
2
Para el caso general de integer pow (), consulte stackoverflow.com/questions/101439/… . Para potencias de 2, solo usa turnos.
Peter Cordes

Respuestas:

8

Para el caso general, la respuesta de @dat_ha es correcta, pero vale la pena señalar que desea un caso muy especial ... poderes de dos. Debido a que las computadoras usan aritmética binaria, las operaciones que involucran potencias de dos a menudo tienen algunos atajos disponibles.

La operación de desplazamiento a la izquierda ( <<), que literalmente desplaza los dígitos de la representación binaria del número (es decir, bits) hacia la izquierda, puede lograr multiplicar un número por una potencia de dos . En la base dos, desplazar bits un lugar a la izquierda es lo mismo que multiplicar por 2, al igual que en la base 10 cambiar dígitos un lugar a la izquierda es lo mismo que multiplicar por 10. Para una explicación completa del operador de desplazamiento a la izquierda en C ++ , vea esta respuesta en Desbordamiento de pila .

Es importante tener en cuenta que el desplazamiento hacia la izquierda puede perder información; Los bits desplazados al final se pierden. Debido a que necesita potencias de 2 a 10, está seguro cuando trabaja con enteros con signo, que tienen un valor máximo de 2^15-1Arduino Uno .

Dadas esas advertencias, aquí hay una función para calcular las potencias de dos dentro de estas restricciones. Este es un código muy rápido porque la operación de desplazamiento a la izquierda es una operación de muy bajo nivel, y en realidad no se realiza ninguna multiplicación.

int pow2(int p){
    return 1 << p;
}
Jason Clark
fuente
Error: puede subir hasta 2 ^ 32 - 1 si usa un unsigned long.
Dat Ha
@DatHa gracias, parecía haber perdido la palabra "firmado" durante la edición. Fijo.
Jason Clark
1
Puede pasar de 2 ^ 32 a 1 si usa una implementación de aritmética de enteros de precisión arbitraria
Dat Han Bag
Me gustaría saber específicamente por qué los resultados de una conversión de enteros en los resultados de pow () NO funcionan para potencias de 2. Para mí, pow (2,3) devuelve 8.00, pero mientras int (8.00) devuelve 8 , int (pow (2,3)) devuelve 7!
KDM
1

Funciona con int, double, longy float. unsigned longy unsigned inttambién debería funcionar. No es necesario que use SOLO flotadores.

Espero que haya ayudado!

Dat Ha
fuente
La razón por la que la respuesta anterior funciona es porque el conjunto de números reales (que contienen flotantes) contiene el conjunto de enteros
Dat Han Bag
@DatHanBag: Y lo más importante, cada entero de 32 bits es exactamente representable por un double. En realidad, dado que el punto flotante IEEE se basa en una representación binaria de mantisa / exponente, cada potencia de 2 debe ser exactamente representable incluso más allá de 2 ^ 53 (el punto donde doubleno puede representar cada entero arbitrario, una unidad 1 en el último lugar de la mantissa es mayor que 1.0).
Peter Cordes
@PeterCordes Sí, lo sabía. Tal vez debería haber dicho "conjuntos acotados" al referirme a conjuntos flotantes y enteros para arduino en mi comentario sobre la respuesta de
Dat Han Bag
44
Esta es una respuesta algo válida a la pregunta general de usar pow()para enteros, pero AFAICT arduino ni siquiera tiene coma flotante de hardware, por lo que es una respuesta terrible. Una pow()implementación entera como esta que se ejecuta en log2 (n) multiplicando el tiempo y agregando para acumular un resultado seguramente funcionará mejor, y no mencionar que los cambios de bits funcionan para potencias de 2 simplemente hace que esta sea una respuesta terrible a esta pregunta.
Peter Cordes
1
@PeterCordes "así que es una respuesta terrible". -confirmó que es una especie de respuesta simplista de baja calidad. pow () es ciertamente computable en log2 (n): el método simple aprendido en la escuela (multiplicar el número por sí mismo a la potencia no es tan eficiente). Puede hacerlo mejor con una transformación de Fourier para enteros realmente grandes, por ejemplo. Pero tal vez el OP lo acepte y le guste.
Dat Han Bag