una - potencias con while c++
¿Por qué mi número entero de matemáticas con std:: pow da la respuesta incorrecta? (5)
No con el mío al menos:
$ g++ --version | head -1
g++ (GCC) 4.7.2 20120921 (Red Hat 4.7.2-2)
$ ./a.out
123
IDEone también está ejecutando la versión 4.7.2 y da 123
.
Firmas de pow()
de http://www.cplusplus.com/reference/cmath/pow/
double pow ( double base, double exponent );
long double pow ( long double base, long double exponent );
float pow ( float base, float exponent );
double pow ( double base, int exponent );
long double pow ( long double base, int exponent );
Debes establecer double base = 10.0;
y double i = 23.0
.
Considere la siguiente pieza de código:
#include <iostream>
#include <cmath>
int main() {
int i = 23;
int j = 1;
int base = 10;
int k = 2;
i += j * pow(base, k);
std::cout << i << std::endl;
}
Sale "122" en vez de "123". ¿Es un error en g ++ 4.7.2 (MinGW, Windows XP)?
Si simplemente escribes
#include <iostream>
#include <cmath>
int main() {
int i = 23;
int j = 1;
int base = 10;
int k = 2;
i += j * pow(base, k);
std::cout << i << std::endl;
}
¿A qué crees que se supone que se refiere pow
? El estándar C ++ ni siquiera garantiza que, después de incluir cmath, tenga una función pow en el alcance global.
Tenga en cuenta que todas las sobrecargas están al menos en el std
nombres std
. Hay funciones pow
que toman un exponente entero y hay funciones pow
que toman exponentes de coma flotante. Es muy posible que su implementación en C ++ solo declare la función C pow en alcance global. Esta función toma un exponente de coma flotante. Lo que pasa es que es probable que esta función tenga un par de errores de aproximación y redondeo. Por ejemplo, una posible forma de implementar esa función es:
double pow(double base, double power)
{
return exp(log(base)*power);
}
Es muy posible que pow (10.0,2.0) produzca algo así como 99.99999999992543453265 debido a errores de aproximación y redondeo. Combinado con el hecho de que la conversión de coma flotante a entero arroja el número antes del punto decimal, esto explica su resultado de 122 porque 99 + 3 = 122.
Intente usar una sobrecarga de pow que tome un exponente entero y / o realice un redondeo apropiado de float a int. La sobrecarga tomando un exponente entero puede darle el resultado exacto para 10 a la 2da potencia.
Editar:
Como señaló, tratar de usar la sobrecarga de std :: pow (double, int) también parece arrojar un valor ligeramente inferior a 100. Me tomé el tiempo para verificar los estándares ISO y la implementación de libstdc ++ para ver que empezando con C ++ 11 las sobrecargas que toman exponentes enteros se han descartado como resultado de la resolución del informe de defectos 550 . Habilitar la compatibilidad con C ++ 0x / C ++ 11 en realidad elimina las sobrecargas en la implementación de libstdc ++ lo que podría explicar por qué no vio ninguna mejora.
De todos modos, probablemente sea una mala idea confiar en la precisión de dicha función, especialmente si se trata de una conversión a un número entero. Un error leve hacia cero obviamente hará una gran diferencia si espera un valor de punto flotante que es un número entero (como 100) y luego lo convierte a un valor de tipo int. Así que mi sugerencia sería escribir tu propia función pow que tome todos los enteros o tener especial cuidado con respecto a la conversión double-> int usando tu propia función de ronda para que un ligero error torwards zero no cambie el resultado.
Todas las otras respuestas hasta ahora se pierden o bailan alrededor del único problema en la pregunta:
El pow
en su implementación C ++ es de mala calidad. Devuelve una respuesta inexacta cuando no es necesario.
Obtenga una mejor implementación de C ++, o al menos reemplace las funciones matemáticas en él. El lipforge.ens-lyon.fr/www/crlibm es bueno.
Tu problema no es un error en gcc, eso es absolutamente cierto. Puede ser un error en la implementación de pow
, pero creo que tu problema es simplemente el hecho de que estás usando pow
que da un resultado impreciso de coma flotante (porque está implementado como algo como exp(power * log(base));
y log(base)
nunca va a ser absolutamente preciso [a menos que la base sea un poder de e].
std::pow()
funciona con números de punto flotante, que no tienen una precisión infinita, y probablemente la implementación de la Biblioteca estándar que está utilizando implementa pow()
de una manera (pobre) que hace que esta falta de precisión infinita se vuelva relevante.
Sin embargo, puede definir fácilmente su propia versión que funcione con enteros. En C ++ 11, incluso puede hacerlo constexpr
(para que el resultado se pueda calcular en tiempo de compilación cuando sea posible):
constexpr int int_pow(int b, int e)
{
return (e == 0) ? 1 : b * int_pow(b, e - 1);
}
Aquí hay un ejemplo en vivo .
Forma recursiva de cola (créditos a Dan Nissenbaum ):
constexpr int int_pow(int b, int e, int res = 1)
{
return (e == 0) ? res : int_pow(b, e - 1, b * res);
}