Pregunta

extrañas cosas suceden cuando intento de encontrar la raíz cúbica de un número.

Las siguientes declaraciones de código me indefinido. En cmd:. -1 # IND

cout<<pow(( double )(20.0*(-3.2) + 30.0),( double )1/3)

Mientras que éste funciona perfectamente bien. En cmd: 4.93242414866094

cout<<pow(( double )(20.0*4.5 + 30.0),( double )1/3)

De forma matemática tiene que trabajar ya que podemos tener la raíz cúbica de un número negativo. Pow es de biblioteca de C ++ Visual math.h 2010. Algunas ideas?

¿Fue útil?

Solución

pow(x, y) de <cmath> no funciona si x es negativo e y es no integral.

Esto es una limitación de std::pow, como se documenta en el estándar C y en cppreference :

  

El manejo de errores

     
      se reportan
  • Errores como se especifica en math_errhandling
  •   
  • Si la base es finito y negativa y exp es finito y no entero, se produce un error de dominio y puede producirse un error de rango.
  •   
  • Si la base es cero y exp es cero, puede producirse un error de dominio.
  •   
  • Si la base es cero y exp es negativo, un error de dominio o puede producirse un error de polos.
  •   

Hay un par de maneras de evitar esta limitación:

  • Cubo de raíces es lo mismo que tomar algo a la potencia 1/3, por lo que podría hacer std::pow(x, 1/3.).

  • En C ++ 11, se puede utilizar std::cbrt . C ++ 11 introdujo tanto de raíz cuadrada y funciones de raíz cúbica, pero no-ésimo n función de raíz genérico que supera las limitaciones de std::pow.

Otros consejos

El 1/3 poder es un caso especial. En general, las funciones no integrales de los números negativos son complejas. No sería práctico para pow para comprobar si hay casos especiales como las raíces de números enteros, y además, 1/3 como un doble no es exactamente 1/3!

No sé acerca de la visual C ++ prisionero de guerra, pero mi página de manual dice en virtud de errores:

  

El EDOM x argumento es negativo y y no es un valor entero. Esto daría lugar a un número complejo.

Se tendrá que utilizar una función raíz cúbica más especializados si desea raíces cúbicas de números negativos -. O esquinas cortadas y tomar valor absoluto, a continuación, tomar raíz cúbica, luego se multiplica la parte posterior señal en

Tenga en cuenta que dependiendo del contexto, un número negativo x al poder 1/3 no es necesariamente la raíz cúbica negativa que está esperando. Podría ser simplemente tan fácilmente la primera raíz compleja, x^(1/3) * e^(pi*i/3). Se trata de los usos de Mathematica convención; también es razonable acaba de decir que es indefinido.

Mientras que (-1) ^ 3 = -1, no se puede simplemente dar un poder racional de un número negativo y esperar una respuesta real. Esto se debe a que hay otras soluciones a este exponente racional que son imaginarias en la naturaleza.
http: / /www.wolframalpha.com/input/?i=x^(1/3),+x+from+-5+to+0

Similarmente, la trama x ^ x. Para x = -1/3, este debería tener una solución. Sin embargo, esta función se considerará indefinido en R para x <0.

Por lo tanto, no espere que math.h hacer magia que haría ineficaz, basta con cambiar las señales usted mismo.

Guess Tienes que tomar lo negativo y lo puso en el después. Usted puede tener un envoltorio de hacer esto para usted si realmente desea.

function yourPow(double x, double y)
{
    if (x < 0)
        return -1.0 * pow(-1.0*x, y);
    else
        return pow(x, y);
}

No eche a double utilizando (double), utilice una constante numérica doble en vez:

double thingToCubeRoot = -20.*3.2+30;
cout<< thingToCubeRoot/fabs(thingToCubeRoot) * pow( fabs(thingToCubeRoot), 1./3. );

debe hacer el truco!

También: no incluyen <math.h> en proyectos de C ++, pero el uso <cmath> lugar

.

Alternativamente, el uso pow de la cabecera <complex> para las razones expuestas por buddhabrot

pow( x, y ) es la misma que (es decir, equivalente a) exp( y * log( x ) )

si log (x) es pow entonces no válido (x, y) es también.

Del mismo modo que puede no realiza 0 a la potencia de nada, aunque matemáticamente debe ser 0.

C ++ 11 tiene la función cbrt (ver por ejemplo http: // en.cppreference.com/w/cpp/numeric/math/cbrt ) para que pueda escribir algo como

#include <iostream>
#include <cmath>

int main(int argc, char* argv[])
{
   const double arg = 20.0*(-3.2) + 30.0;
   std::cout << cbrt(arg) << "\n";
   std::cout << cbrt(-arg) << "\n";
   return 0;
}

No tengo acceso al C ++ estándar, de modo que no sé cómo se maneja el argumento negativo ... una prueba en Ideone http://ideone.com/bFlXYs parece confirmar que C ++ (gcc-4.8.1) se extiende la raíz cúbica con esta regla cuando cbrt(x)=-cbrt(-x) x<0; para esta extensión se puede ver http://mathworld.wolfram.com/CubeRoot.html

Yo estaba buscando la raíz de codo y encontró este hilo y se me ocurre que el siguiente código podría funcionar:

#include <cmath>
using namespace std;

function double nth-root(double x, double n){
    if (!(n%2) || x<0){
        throw FAILEXCEPTION(); // even root from negative is fail
    }

    bool sign = (x >= 0);

    x = exp(log(abs(x))/n);

    return sign ? x : -x;
}

Creo que no debe confundirse con la exponenciación nth root de un número. Ver lo bueno Wikipedia

debido a que la tercera siempre devolverá 0, ya que será considerado como entero ... tratar con 1.0 / 3.0 ... Es lo que yo creo, pero intento y poner en práctica ... y no se olvide que declarar las variables que contienen 1.0 y 3.0 como doble ...

Aquí hay una pequeña función Golpeé hacia arriba.

#define uniform() (rand()/(1.0 + RAND_MAX))

double CBRT(double Z)
{
    double guess = Z;
    double x, dx;
    int loopbreaker;

retry:
    x = guess * guess * guess;
    loopbreaker = 0;
    while (fabs(x - Z) > FLT_EPSILON)
    {
        dx = 3 * guess*guess;
        loopbreaker++;
        if (fabs(dx) < DBL_EPSILON || loopbreaker > 53)
        {
            guess += uniform() * 2 - 1.0;
            goto retry;
        }
        guess -= (x - Z) / dx;
        x = guess*guess*guess;
    }

    return guess;
}

Se utiliza de Newton-Raphson para encontrar una raíz cúbica.

En algún momento Newton -Raphson se atasca, si la raíz está muy cerca de 0, entonces la lata derivado obtener grandes y que puede oscilar. Así que he sujeta y lo obligó a reiniciar si eso sucede. Si necesita más precisión puede cambiar los FLT_EPSILONs.

Si alguna vez tiene ninguna biblioteca matemática puede utilizar esta forma de calcular la raíz cúbica:

raíz cúbica

double curt(double x) {
  if (x == 0) {
    // would otherwise return something like 4.257959840008151e-109
    return 0;
  }
  double b = 1; // use any value except 0
  double last_b_1 = 0;
  double last_b_2 = 0;
  while (last_b_1 != b && last_b_2 != b) {
    last_b_1 = b;
    // use (2 * b + x / b / b) / 3 for small numbers, as suggested by  willywonka_dailyblah
    b = (b + x / b / b) / 2;
    last_b_2 = b;
    // use (2 * b + x / b / b) / 3 for small numbers, as suggested by  willywonka_dailyblah
    b = (b + x / b / b) / 2;
  }
  return b;
}

Es deriva del algoritmo sqrt continuación. La idea es que b y x / b / b más grande y más pequeño de la raíz cúbica de x. Por lo tanto, el promedio de los dos encuentra más cerca de la raíz cúbica de x.

Raíz cuadrada y raíz cúbica (en Python)

def sqrt_2(a):
    if a == 0:
        return 0
    b = 1
    last_b = 0
    while last_b != b:
        last_b = b
        b = (b + a / b) / 2
    return b

def curt_2(a):
    if a == 0:
        return 0
    b = a
    last_b_1 = 0;
    last_b_2 = 0;
    while (last_b_1 != b and last_b_2 != b):
        last_b_1 = b;
        b = (b + a / b / b) / 2;
        last_b_2 = b;
        b = (b + a / b / b) / 2;
    return b

A diferencia de la raíz cuadrada, y last_b_1 last_b_2 se requieren en la raíz cúbica porque b parpadea. Puede modificar estos algoritmos para calcular la raíz cuarta, quinta raíz y así sucesivamente.

Gracias a mi profesor de matemáticas Herr Brenner en el grado 11 que me dijo que este algoritmo para sqrt.

Rendimiento

he comprobado en un Arduino con frecuencia de reloj de 16 MHz:

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top