2015-06-09 27 views
8

Invece, questa operazione restituisce -1.IND, poiché sqrt(-1) restituisce -1.IND. L'errore di dominio menzionato sul numero che questo sqrt restituisce per i valori negativi non mantiene l'informazione che questo è in realtà i?Perché non pow (sqrt (-1), 2) restituisce -1?

Esiste un modo per eseguire questa operazione per tutti i numeri negativi, in modo che restituisca il valore corretto, ovvero pow(sqrt(-36), 2) restituirà -36?

+0

Per definizione, la potenza uniforme di un numero reale è positiva. – bereal

+8

Quello che ti serve è una libreria di numeri complessi. – Mysticial

+0

Se qualcosa, dovrebbe eccetto o restituire 0, (perché la parte reale è 0 e 0^2 è 0). –

risposta

12

È possibile utilizzare std::complex per raggiungere il tuo obiettivo, in questo modo:

#include <complex> 
#include <iostream> 

int main() { 
    const std::complex<double> result = 
    std::pow(std::sqrt(std::complex<double>(-36,0)), 2); 
    std::cout << result << std::endl; 
    std::cout << "Real part = " << result.real() << std::endl; 
} 

uscita:

(-36,0) 
Real part = -36 

noti che std::sqrt(std::complex) viene utilizzato qui.


Il motivo dietro il comportamento che si incontra è la firma di sqrt, vale a dire:

doppia sqrt (double x);

float sqrt (float x);

long double sqrt (long double x);

doppio sqrt (T x); // sovraccarichi aggiuntivi per tipi integrali

il che significa che non importa quale prototipo verrà utilizzato, si stanno ottenendo niente di meglio che un nan (o un + -inf), dal momento che i tipi restituiti non può sostenere la parte immaginaria . Ecco perché esiste std::complex.

Quindi, sqrt(-1) sarà sostituito da un nan probabilmente, che non può essere trattato da pow(), in modo che -1 resti intatto, a causa dell'esponente. Di conseguenza, le informazioni sono già perse dopo che la chiamata a sqrt() e pow() non può fare nulla al riguardo.

+0

Penso che cppreference abbia una migliore descrizione di [std :: sqrt] (http://en.cppreference.com/w/cpp/numeric/math/sqrt). –

+0

Sì @ShafikYaghmour, cppreference è una buona alternativa. – gsamaras

3

std::sqrt is defined per restituire l'errore definito dall'implementazione su un errore di dominio. In questo caso (arg := -1) < -0 è un errore di dominio.

std::pow is also defined per restituire un errore definito dall'implementazione su un errore di dominio.

Quindi ricevere -1.Ind è una soluzione plausibile.

Come evidenziato da Mystical, è necessaria una libreria di numeri complessi.

6

Poiché si chiama la funzione double sqrt(double) e il valore di ritorno double può memorizzare solo numeri reali, infinito (con segno) o NaN. Non c'è rappresentazione per i.

Se si desidera memorizzare numeri complessi, utilizzare std::complex.

4

Da this sqrt reference page:

Se l'argomento è inferiore a -0, FE_INVALID è sollevato e viene restituito NaN.

E poi da this pow reference page

... se uno degli argomenti è NaN, NaN viene restituito

Quindi semplicemente non si può utilizzare pow(sqrt(x), y) per qualsiasi vera x che è negativo.

+0

Anche molto bella spiegazione, mi chiedo perché ha 0 upvotes. Farà quel cambiamento! – gsamaras

0

Se è possibile utilizzare C++ 14 è possibile utilizzare gli operatori letterali per complesso: # include

<complex> 
#include <iostream> 

int 
main() 
{ 
    using namespace std::literals::complex_literals; 
    auto z = std::pow(std::sqrt(-36.0 + 0.0i), 2.0); 
    std::cout << z << '\n'; 
} 

L'esecuzione di questo ottengo:

[email protected]:~$ ./cpow 
(-36,4.40873e-15) 

so recente gcc e clang sostenere questo. Sembra che lo sia anche VS2015.

Questa è in realtà un'aggiunta post-C++ 14 ma è ancora in uno spazio dei nomi std anziché experimental.

Problemi correlati