Domanda

Strane cose accadono quando si tenta di trovare la radice cubica di un numero.

I seguenti restituisce il codice di me undefined. In cmd:. -1 # IND

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

Anche se questo funziona perfettamente bene. In cmd: 4,93242414866094

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

Da modo matematico deve funzionare dal momento che siamo in grado di avere la radice cubica di un numero negativo. Pow è da C 2010 biblioteca math.h visiva ++. Tutte le idee?

È stato utile?

Soluzione

pow(x, y) da <cmath> non funziona se x è negativo ey non integrale.

Questa è una limitazione di std::pow, come documentato nello standard C e cppreference :

  

La gestione degli errori

     
      
  • Gli errori vengono segnalati come specificato nella math_errhandling
  •   
  • Se la base è finito e negativo e exp è finito e non intero, si verifica un errore di dominio e può verificarsi un errore di campo.
  •   
  • Se la base è pari a zero e exp è pari a zero, potrebbe verificarsi un errore di dominio.
  •   
  • Se la base è zero e exp è negativa, un errore di dominio oppure potrebbe verificarsi un errore di polo.
  •   

Ci sono un paio di modi per aggirare questa limitazione:

  • Cube-radicamento è lo stesso di prendere qualcosa al potere 1/3, in modo che si possa fare std::pow(x, 1/3.).

  • In C ++ 11, è possibile utilizzare std::cbrt . C ++ 11 illustra sia funzioni cubo-radice radice quadrata e, ma non-esima n funzione radice generica che supera i limiti di std::pow.

Altri suggerimenti

Il 1/3 potere è un caso speciale. In generale, i poteri non integranti di numeri negativi sono complesse. Non sarebbe pratico per pow per verificare la presenza di casi particolari come radici intere, e inoltre, 1/3 come una doppia non è esattamente 1/3!

Non so circa il C ++ visivo pow, ma la mia pagina uomo dice sotto gli errori:

  

EDOM Il x argomento è negativo e y non è un valore integrale. Ciò si tradurrebbe in un numero complesso.

Si dovrà utilizzare una funzione radice cubica più specializzati, se si desidera radici cubiche di numeri negativi -. O angoli tagliati e prendere valore assoluto, quindi prendere radice cubica, poi moltiplicare il segno indietro

Si noti che a seconda del contesto, un numero negativo x alla potenza 1/3 non è necessariamente la radice cubica negativo vi aspettate. Potrebbe essere benissimo la prima radice complesso, x^(1/3) * e^(pi*i/3). Questo è usi convenzione Mathematica; è anche ragionevole dire solo che è indefinito.

Mentre (-1) ^ 3 = -1, non si può semplicemente prendere un potere razionale di un numero negativo e si aspettano una risposta reale. Questo è perché ci sono altre soluzioni a questo esponente razionale che sono immaginari in natura.
http: / /www.wolframalpha.com/input/?i=x^(1/3),+x+from+-5+to+0

Similmente, la trama x ^ x. Per x = -1/3, questo dovrebbe avere una soluzione. Tuttavia, questa funzione si considera undefined in R per x <0.

Quindi, non aspettatevi math.h fare magia che renderebbe inefficiente, basta cambiare i segni stessi.

Indovinate devi prendere il negativo fuori e metterlo in seguito. Si può avere un wrapper fare questo per voi, se si vuole veramente.

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

Do not cast double utilizzando (double), utilizzare una costante numerica doppia invece:

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

dovrebbe fare il trucco!

Inoltre: non comprendono <math.h> in progetti C ++, ma l'uso <cmath> invece

.

In alternativa, l'uso pow dal collettore <complex> per i motivi indicati dalla buddhabrot

pow( x, y ) è lo stesso (cioè equivalente a) exp( y * log( x ) )

se log (x) non è valida pow allora (x, y) è anche.

Allo stesso modo non è possibile eseguire 0 al potere di qualsiasi cosa, anche se matematicamente dovrebbe essere 0.

C ++ 11 ha la funzione cbrt (vedi ad esempio http: // en.cppreference.com/w/cpp/numeric/math/cbrt ) in modo da poter scrivere qualcosa di simile

#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;
}

Non ho accesso al C ++ standard in modo da non so come l'argomento negativo è gestita ... un test su Ideone http://ideone.com/bFlXYs sembra confermare che C ++ (gcc-4.8.1) estende la radice cubica con questa regola quando cbrt(x)=-cbrt(-x) x<0; per questa estensione è possibile vedere http://mathworld.wolfram.com/CubeRoot.html

ero alla ricerca di radici cubito e ha trovato questa discussione e mi viene in mente che il seguente codice potrebbe funzionare:

#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;
}

Credo che non si dovrebbe confondere elevamento a potenza con l'ennesima radice di un numero. Vedere il buon vecchio Wikipedia

perché il terzo sarà sempre ritornare 0 in quanto sarà considerato come intero ... provare con 1.0 / 3.0 ... è quello che penso ma cerco di implementare ... e non dimenticate di dichiarare le variabili che contengono 1.0 e 3.0 come doppio ...

Ecco una piccola funzione Ho bussato su.

#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;
}

Si utilizza Newton-Raphson per trovare una radice cubica.

Qualche Newton -Raphson si blocca, se la radice è molto vicino a 0 allora il barattolo derivato ottenere grande e può oscillare. Così ho Strinsi e costretto a riavviare se ciò accade. Se avete bisogno di più la precisione è possibile modificare le FLT_EPSILONs.

Se avete mai avuto alcun libreria matematica è possibile utilizzare in questo modo per calcolare la radice cubica:

radice cubica

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;
}

E 'deriva dalla algoritmo di sqrt di seguito. L'idea è che b e x / b / b grande e più piccola dalla radice cubica di x. Così, la media dei due si trova più vicino alla radice cubica di x.

Radice quadrata e radice cubica (in 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

In contrasto con la radice quadrata, last_b_1 e last_b_2 sono richiesti nella radice cubica perché b sfarfallio. È possibile modificare questi algoritmi per calcolare la radice quarta, quinta radice e così via.

Grazie al mio insegnante di matematica Herr Brenner nel 11 ° grado che mi ha detto questo algoritmo per sqrt.

Prestazioni

ho testato su un Arduino con frequenza di clock 16 MHz:

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top