¿Por qué pow(n,2) devuelve 24 cuando n=5, con mi compilador y sistema operativo?

6 minutos de lectura

avatar de usuario
ex serpiente

#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.

¿Qué está pasando?

Sé que el pow función devuelve un double pero 25 se ajusta a un tipo int, entonces, ¿por qué este código imprime un 24 en lugar de un 25? Si n=4; n=6; n=3; n=2; el código funciona, pero con los cinco no.

  • Puede intentar tomar el valor de retorno de pow en un float o double variable, luego intente encasillarla en int. A ver si eso también produce 24 o la respuesta correcta 25

    – No te preocupes niño

    5 de septiembre de 2014 a las 4:25

  • @exsnake – El pow función no hace simplemente una multiplicación de 5 * 5. El resultado final es probablemente 24.9999999 o resultado similar. Él pow La función probablemente usa logaritmos para calcular el resultado, ya que también tiene que manejar potencias fraccionarias. Para confirmar, mire la implementación de su compilador de pow.

    – Paul McKenzie

    5 de septiembre de 2014 a las 4:35


  • Debe aclarar qué sistema operativo está utilizando, ya que es casi seguro que se trata de un error en su implementación de la parte matemática de la biblioteca estándar. Supongo que estás usando mingw con MSVCRT en Windows…

    – R.. GitHub DEJA DE AYUDAR A ICE

    5 de septiembre de 2014 a las 4:55

  • ¿Puedes compartir la salida de printf("%.25lf\n", pow(n,2)); en su implementación donde n=5?

    -Mohit Jain

    5 de septiembre de 2014 a las 5:08

  • Un bien pow(n,2) devolvería resultados exactamente correctos. C no especifica cómo bueno pow() debe ser.

    – chux – Reincorporar a Monica

    5 sep 2014 a las 14:35

avatar de usuario
pablomckenzie

Esto es lo que puede estar sucediendo aquí. Debería poder confirmar esto observando la implementación de su compilador del pow función:

Suponiendo que tiene los #include correctos (todas las respuestas anteriores y los comentarios sobre esto son correctos, no tome la #include archivos por sentado), el prototipo para el estándar pow la funcion es esta:

double pow(double, double);

y estas llamando pow Me gusta esto:

pow(5,2);

Él pow La función pasa por un algoritmo (probablemente usando logaritmos), por lo tanto, usa funciones y valores de coma flotante para calcular el valor de la potencia.

Él pow función no pasa por un ingenuo “multiplicar el valor de xa total de n veces”, ya que también tiene que calcular pow usando exponentes fraccionarios, y no puedes calcular potencias fraccionarias de esa manera.

Entonces, lo más probable es que el cálculo de pow el uso de los parámetros 5 y 2 resultó en un ligero error de redondeo. Cuando te asignan a un inttruncaste el valor fraccionario, dando así 24.

Si está utilizando números enteros, también podría escribir su propio “intpow” o una función similar que simplemente multiplique el valor la cantidad de veces requerida. Los beneficios de esto son:

  1. No entrará en la situación en la que puede obtener errores de redondeo sutiles usando pow.

  2. Su intpow Lo más probable es que la función se ejecute más rápido que una llamada equivalente a pow.

  • Si vas a hacer rodar tu propia potencia entera, probablemente deberías usar exponenciación al cuadrado en lugar de la multiplicación repetida ya que esta última es Sobre) y el primero es O (registro n).

    – aruisdante

    09/10/2014 a las 20:43

  • @aruisdante: Cuidado, la notación sugiere un cambio de complejidad lineal a logarítmica, cuando en realidad es un cambio de pseudo-lineal a la complejidad lineal.

    – Ben Voigt

    2 de noviembre de 2016 a las 2:54

  • @BenVoigt Técnicamente, el comentario anterior debería haber sido más específico: el algoritmo ingenuo requiere operaciones aritméticas O (n) (multiplicación o suma) donde n es el exponente; elevar al cuadrado reduce esto a O(log(n)). Si tomamos el número de bits en n como el tamaño del problema, también podríamos querer contar el número de bits en cada producto y no considerar la multiplicación como una operación de tiempo constante. Para las preocupaciones prácticas de las personas que realizan cálculos numéricos, creo que la página de Wikipedia es demasiado pedante; para las preocupaciones teóricas de la complejidad, su corrección es cuestionable.

    – David K.

    10 dic 2016 a las 17:50

Desea un resultado int de una función destinada a dobles.

Tal vez deberías usar

ele=(int)(0.5 + pow(n,2));
/*    ^    ^              */
/* casting and rounding   */

  • mejor usar ele = round(0.5 + pow(n,2));. Aunque en este caso pow(n,2) no debe devolver resultados inferiores a cero, y = (int)(0.5 +x) es un problema para negativo x.

    – chux – Reincorporar a Monica

    5 sep 2014 a las 14:30


  • ¡No mejor! solo debes usar round(pow(n,2)). agregar 0.5 antes de redondear efectivamente redondea al siguiente entero. Si pow(n,2) devolvió 25 más épsilon, obtendría 26.

    – chqrlie

    24 de febrero de 2015 a las 1:55

La aritmética de punto flotante no es exacta.

Aunque los valores pequeños se pueden sumar y restar exactamente, el pow() La función normalmente funciona multiplicando logaritmos, por lo que incluso si las entradas son exactas, el resultado no lo es. Asignando a int siempre se trunca, por lo que si la inexactitud es negativa, obtendrá 24 en lugar de 25.

La moraleja de esta historia es usar operaciones con números enteros sobre números enteros, y desconfiar de <math.h> funciones cuando los argumentos reales se van a promover o truncar. Es lamentable que GCC no avise a menos que agregue -Wfloat-conversion (no está en -Wall -Wextraprobablemente porque hay muchos casos en los que se prevé y desea dicha conversión).

Para potencias enteras, siempre es más seguro y rápido usar la multiplicación (división si es negativa) en lugar de pow() – ¡reserva este último para donde lo necesites! Sin embargo, tenga en cuenta el riesgo de desbordamiento.

avatar de usuario
Jayesh Bhoi

Cuando usa pow con variables, su resultado es double. Asignación a un int lo trunca.

Entonces puede evitar este error asignando el resultado de pow para double o float variable.

Así que básicamente

se traduce a 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. Así por ejemplo 5^2 se convertirá 24.9999996 o 25.00002

Si no lo hace #include <math.h> entonces el compilador no conoce los tipos de argumentos a pow() que son ambos double no int — entonces obtienes un resultado indefinido. Obtienes 24, obtengo 16418.

  • OP incluye matemáticas.h. no es una oportunidad de obtener un resultado ligeramente incorrecto al no incluir math.h. por lo tanto nosotros un problema completamente diferente.

    – Jean-François Fabre

    31 de agosto de 2017 a las 6:31


  • @Jean-FrançoisFabre (suspiro) el OP NO incluía math.h, la pregunta se editó para agregarla.

    – John Hascall

    3 de marzo de 2020 a las 17:48

  • OP incluye matemáticas.h. no es una oportunidad de obtener un resultado ligeramente incorrecto al no incluir math.h. por lo tanto nosotros un problema completamente diferente.

    – Jean-François Fabre

    31 de agosto de 2017 a las 6:31


  • @Jean-FrançoisFabre (suspiro) el OP NO incluía math.h, la pregunta se editó para agregarla.

    – John Hascall

    3 de marzo de 2020 a las 17:48

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad