2016-04-12 39 views
11

Ho incontrato un comportamento confuso con radici quadrate di numeri complessi in python. L'esecuzione di questo codice:Radice quadrata di numeri complessi in python

from cmath import sqrt 
a = 0.2 
b = 0.2 + 0j 
print(sqrt(a/(a - 1))) 
print(sqrt(b/(b - 1))) 

dà l'uscita

0.5j 
-0.5j 

Una cosa simile accade con

print(sqrt(-1 * b)) 
print(sqrt(-b)) 

Sembra queste coppie di affermazioni dovrebbe dare la stessa risposta?

+0

Secondo [Wolfram] (https://www.wolframalpha.com/) Lei ha ragione. La prima coppia ([link] (https://www.wolframalpha.com/input/?i=sqrt (0.2 +% 2F + (0.2 + - + 1))) e [link] (https: //www.wolframalpha .com/input /? i = sqrt (+ (0.2% 2B0i) +% 2F + (+ (0.2% 2B0i) + - 1+)))) entrambi dovrebbero essere '0.5i', e la seconda coppia ([link] (https://www.wolframalpha.com/input/?i=sqrt(-1+*+(+.2+%2B+0i))) e [link] (https://www.wolframalpha.com/input/ ? i = sqrt (-1 + * + (0.2 +% 2B + 0i)))) dovrebbero entrambi essere '0.447214 ... i'. La fonte di 'cmath.sqrt()' è [qui] (https://hg.python.org/cpython/file/tip/Modules/cmathmodule.c#l732) ... – Jens

+6

Entrambe le risposte sono corrette, la domanda è il motivo per cui restituisce diversi coniugati. – tzaman

+0

FWIW il comportamento appare lo stesso in 2.7 e 3.5. – tzaman

risposta

8

Entrambe le risposte (+0.5j e -0.5j) sono corrette, dal momento che sono complex conjugates - vale a dire la parte reale è identico, e la parte immaginaria è segno-capovolto.

Guardando il code rende il comportamento chiaro - la parte immaginaria del risultato ha sempre lo stesso segnocome la parte immaginaria degli input, come si è visto nelle linee 790 e 793:

r.imag = copysign(d, z.imag); 

Dal a/(a-1) è 0.25 che è implicitamente 0.25+0j si ottiene un risultato positivo; b/(b-1) produce 0.25-0j (per qualche motivo, non sono sicuro del motivo per cui non corrisponde a 0.25+0j tbh) quindi il risultato è ugualmente negativo.

MODIFICA: This question ha alcune discussioni utili sullo stesso problema.

+0

'a/(a ​​- 1)' è '-0.25'. La conversione in un insieme ti dà '-0.25 + 0j'. Con b, ottieni '-0.25-0j'. – Seth

+0

La [documentazione] (https://docs.python.org/2/library/cmath.html#cmath.sqrt) specifica anche che il taglio del ramo viene scelto per essere lungo un raggio da 0 a -∞, il che darebbe il comportamento osservato. È interessante notare che 'b/(b-1)' fornisce uno zero negativo per il componente immaginario, comunque. – user2357112

+0

@ user2357112 si, è piuttosto strano, non sono sicuro del perché lo faccia. Digitando semplicemente '1-0j' come letterale in IDLE si ottiene' 1 + 0j' come valore. È interessante notare che '-0j' produce di per sé '-0-0j'. – tzaman

1

Posso rispondere perché questo sta accadendo, ma non perché è stato scelto il comportamento.

a/(a - 1) 

viene valutato come 0,2/-0.8, che è -0.25, che viene convertito in un numero complesso da cmath.sqrt, mentre

b/(b - 1) 

viene valutato come (0,2 + 0j)/(- 0,8 + 0J) che è (-0.25-0j), che viene convertito in un numero complesso con un componente complesso negativo.

Per un esempio più semplice,

cmath.sqrt(0j) == 0j 
cmath.sqrt(-0j) == -0j