2012-11-14 74 views
17

Tôi tự hỏi về cách Python (3.3.0) in số phức. Tôi đang tìm một lời giải thích, không phải là cách để thay đổi bản in.Định dạng số phức trong Python

Ví dụ:

>>> complex(1,1)-complex(1,1) 
0j 

Tại sao không phải nó chỉ in "0"? Tôi đoán là: để giữ đầu ra kiểu phức tạp.

dụ tiếp theo:

>>> complex(0,1)*-1 
(-0-1j) 

Vâng, một "-1j" đơn giản hoặc "(-1j)" đã có thể làm. Và tại sao "-0" ?? Không phải là giống như +0? Nó dường như không phải là một vấn đề làm tròn:

>>> (complex(0,1)*-1).real == 0.0 
True 

Và khi phần ảo được tích cực, -0 biến mất:

>>> complex(0,1) 
1j 
>>> complex(0,1)*-1 
(-0-1j) 
>>> complex(0,1)*-1*-1 
1j 

Tuy nhiên, một ví dụ:

>>> complex(0,1)*complex(0,1)*-1 
(1-0j) 
>>> complex(0,1)*complex(0,1)*-1*-1 
(-1+0j) 
>>> (complex(0,1)*complex(0,1)*-1).imag 
-0.0 

Am Tôi thiếu cái gì ở đây?

+0

Về 'phần 0j', đó là thực tế phổ biến trong python rằng 'eval (repr (x)) == x' –

Trả lời

14

Nó in 0j để cho biết rằng nó vẫn là giá trị complex. Bạn cũng có thể gõ nó trở lại theo cách đó:

>>> 0j 
0j 

Phần còn lại có lẽ là kết quả của sự kỳ diệu của IEEE 754 floating point representation, mà làm cho một sự phân biệt giữa 0 và -0, cái gọi là signed zero. Về cơ bản, có một bit cho biết số liệu là dương hay âm, bất kể số liệu có phải là số không. Điều này giải thích lý do tại sao 1j * -1 cho một cái gì đó với một phần thực không tiêu cực: số không dương đã nhân với -1.

-0 được yêu cầu theo tiêu chuẩn để so sánh bằng +0, điều này giải thích tại sao (1j * -1).real == 0.0 vẫn giữ.

Lý do mà Python vẫn quyết định in -0, là trong thế giới phức tạp này tạo sự khác biệt cho việc cắt giảm chi nhánh, ví dụ trong the phase function:

>>> phase(complex(-1.0, 0.0)) 
3.141592653589793 
>>> phase(complex(-1.0, -0.0)) 
-3.141592653589793 

này là về phần ảo, không phần thực sự, nhưng thật dễ dàng để tưởng tượng các tình huống mà dấu hiệu của phần thực sẽ tạo ra sự khác biệt tương tự.

+2

Tôi chỉ muốn thêm vào câu trả lời này, rằng tất cả các trường hợp được mô tả là hợp lệ và python công trình như mong đợi. Bạn có thể tìm thấy trường hợp thử nghiệm đặc biệt với tất cả các biểu diễn liên quan đến IEEE 754: 'Lib/tests/test_complex.py',' test_negative_zero_repr_str' –

+1

Chỉ cần kiểm tra và có vẻ như bạn đã đúng về '-0':' >>> 0j.real .hex() ' ' '0x0.0p + 0'' '>>> (0j * -1) .real.hex()' '' -0x0.0p + 0'' –

+0

Tôi xác nhận' - 0' phần: 'in (0.0 * -1)' in "' -0.0' ". Và vì kiểu 'complex' trong Python là một cặp số _float_, không quan trọng bạn có chỉ định phần phân số hay không. –

1

Theo như câu hỏi đầu tiên có liên quan: nếu nó chỉ in 0 nó sẽ được toán học chính xác, nhưng bạn sẽ không biết bạn đang đối phó với một đối tượng complex so với int. Miễn là bạn không chỉ định .real bạn sẽ luôn nhận được một thành phần J.

Tôi không chắc chắn lý do bạn sẽ nhận được -0; nó không phải là kỹ thuật không chính xác (-1 * 0 = 0) nhưng nó là cú pháp lẻ.

Theo như phần còn lại đi, thật lạ là nó không nhất quán, tuy nhiên không có chính xác về mặt kỹ thuật, chỉ là một tạo phẩm của việc thực hiện.

3

Câu trả lời nằm trong chính mã nguồn Python.

Tôi sẽ làm việc với một trong các ví dụ của bạn. Hãy

a = complex(0,1) 
b = complex(-1, 0) 

Khi bạn làm a*b bạn đang gọi điện thoại this function:

real_part = a.real*b.real - a.imag*b.imag 
imag_part = a.real*b.imag + a.imag*b.real 

Và nếu bạn làm điều đó trong các thông dịch viên python, bạn sẽ nhận được

>>> real_part 
-0.0 
>>> imag_part 
-1.0 

Từ IEEE754, bạn đang nhận được một negative zero và kể từ that's not +0, bạn sẽ nhận được giấy phép và phần thực khi in.

if (v->cval.real == 0. && copysign(1.0, v->cval.real)==1.0) { 
    /* Real part is +0: just output the imaginary part and do not 
     include parens. */ 
... 
else { 
    /* Format imaginary part with sign, real part without. Include 
     parens in the result. */ 
... 

Tôi đoán (nhưng tôi không biết chắc chắn) mà lý do xuất phát từ tầm quan trọng của dấu hiệu cho thấy khi tính toán với chức năng phức tạp tiểu học (có một tài liệu tham khảo cho điều này trong các bài viết trên wikipedia ký zero).

2
  • 0j là một imaginary literal mà thực sự chỉ ra một số phức tạp chứ không phải là một số nguyên hoặc dấu phẩy một.

  • +-0 ("chữ số không") là kết quả của sự phù hợp của Python với IEEE 754 floating point representation vì trong Python, complex is by definition a pair of floating point numbers. Do sau này, không cần phải in hoặc chỉ định các phần không phân số cho một số complex.

  • Phần -0in nhằm thể hiện chính xác nội dung as repr()'s documentation demands (repr() được mặc nhiên được gọi bất cứ khi nào kết quả của một hoạt động là đầu ra cho giao diện điều khiển).

  • Về câu hỏi lý do tại sao (-0+1j) = 1j nhưng (1j*-1) = (-0+1j). Lưu ý rằng (-0+0j) hoặc (-0.0+0j) không phải là số phức đơn lẻ nhưng biểu thức - một int/float được thêm vào complex. Để tính toán kết quả, trước tiên số đầu tiên được chuyển đổi thành một số complex (-0 ->(0.0,0.0) vì số nguyên không có số 0 đã ký, -0.0 ->(-0.0,0.0)). Sau đó, .real.imag của nó là được thêm vào số tương ứng là 1j(+0.0,1.0). Kết quả là (+0.0,1.0): ^). Để xây dựng một tổ hợp trực tiếp, hãy sử dụng complex(-0.0,1).

+0

Cảm ơn bạn đã giải thích về str/repr. Nhưng ở đây một "print (0j * -1)" vẫn trả về "(-0 + 0j)", vì vậy nó hoạt động giống nhau. Hơn nữa, * nếu * python bám chặt vào tiêu chuẩn IEEE với repr(), tại sao "0 (0 + 0j)" trả về "0j"? – cxxl

+0

2cxxl: '(-0 + 0j)' không phải là một số phức duy nhất mà là một biểu thức - một số nguyên được thêm vào một phức. Khi kết quả được tính, '-0' được chuyển thành một phức và được thêm vào' .real' là '0'. Kết quả là '+ 0': ^) –

+0

Vì giả định của tôi về' str() 'đã được chứng minh là sai trong trường hợp này, tôi đã xóa nó. –

Các vấn đề liên quan