programa - ¿Por qué pow(n, 2) devuelve 24 cuando n=5, con mi compilador y mi sistema operativo?
errores de sintaxis en c++ (5)
Cuando usas pow con variables, su resultado es double
. Asignar a un int
trunca.
Entonces puede evitar este error asignando el resultado de pow
a la variable double
o float
.
Así que básicamente
Se traduce en exp(log(x) * y)
que producirá un resultado que no es precisamente el mismo que x^y
- solo una aproximación cercana como un valor de coma flotante. Entonces, por ejemplo, 5^2
se convertirá en 24.9999996
o 25.00002
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main()
{
int n,i,ele;
n=5;
ele=pow(n,2);
printf("%d",ele);
return 0;
}
La salida es 24
.
Estoy usando GNU / GCC en Code :: Blocks.
¿Que esta pasando?
Sé que la función pow
devuelve un double
, pero 25
ajusta a un tipo int, ¿por qué este código imprime 24
lugar de 25
? Si n=4; n=6; n=3; n=2;
n=4; n=6; n=3; n=2;
el código funciona, pero con los cinco no funciona.
Esto es lo que puede estar pasando aquí. Debería poder confirmar esto observando la implementación de la función pow
por parte de su compilador:
Suponiendo que tenga los #incluidos correctos, (todas las respuestas y comentarios anteriores sobre esto son correctos, no tome por sentado los archivos #include
), el prototipo de la función estándar de pow
es este:
double pow(double, double);
y llamas pow
como esta:
pow(5,2);
La función pow
pasa por un algoritmo (probablemente usando logaritmos), por lo tanto usa funciones y valores de punto flotante para calcular el valor de potencia.
La función pow
no pasa por un ingenuo "multiplicar el valor de x un total de n veces", ya que también tiene que calcular el poder usando exponentes fraccionarios, y no se pueden calcular poderes fraccionarios de esa manera.
Por lo tanto, lo más probable es que el cálculo de pow
utilizando los parámetros 5 y 2 dio como resultado un ligero error de redondeo. Cuando asignó un int
, truncó el valor fraccionario, obteniendo 24.
Si usa números enteros, también podría escribir su propia función "intpow" o similar que simplemente multiplique el valor el número de veces requerido. Los beneficios de esto son:
No entrarás en la situación en la que puedes obtener errores de redondeo sutiles al usar
pow
.intpow
probable que tu funciónintpow
se ejecute más rápido que una llamada equivalente apow
.
Quieres el resultado int de una función para dobles.
Quizás deberías usar
ele=(int)(0.5 + pow(n,2));
/* ^ ^ */
/* casting and rounding */
Si no #include <math.h>
entonces el compilador no conoce los tipos de argumentos de pow()
que son double
no int
, por lo que obtiene un resultado indefinido. Tienes 24, obtengo 16418.
La aritmética de coma flotante no es exacta.
Aunque se pueden agregar y restar pequeños valores exactamente, la función pow()
funciona normalmente multiplicando logaritmos, por lo que incluso si las entradas son ambas exactas, el resultado no lo es. Asignar a int
siempre trunca, por lo que si la inexactitud es negativa, obtendrá 24 en lugar de 25.
La moraleja de esta historia es usar operaciones enteras en enteros, y desconfiar de las funciones <math.h>
cuando los argumentos reales se deben promover o truncar. Es desafortunado que GCC no advierta a menos que agregue -Wfloat-conversion
(no está en -Wall -Wextra
, probablemente porque hay muchos casos en que dicha conversión se anticipa y se desea).
Para las potencias enteras, siempre es más seguro y más rápido usar la multiplicación (división si es negativa) en lugar de pow()
- ¡reserva la última para donde sea necesaria! Sin embargo, tenga en cuenta el riesgo de desbordamiento.