2016-02-15 16 views
5

Đây không thực sự là một vấn đề, nó là một cái gì đó tò mò hơn về số học dấu chấm động trên thực hiện Python.Tại sao phân chia gần bằng không có các hành vi khác nhau trong python?

Ai đó có thể giải thích hành vi sau?

>>> 1/1e-308 
1e+308 
>>> 1/1e-309 
inf 
>>> 1/1e-323 
inf 
>>> 1/1e-324 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
ZeroDivisionError: float division by zero 

Dường như 1 chia cho một số gần zero là inf và nếu nó là gần với một ZeroDivisionError được ném. Có vẻ như một hành vi kỳ quặc.

Cùng một đầu ra cho trăn 2.x/3.x.


EDIT: Câu hỏi chính của tôi ở đây là lý do tại sao chúng tôi nhận inf cho một số phạm vi và không ZeroDivisionError giả python mà dường như để xem xét như zero 1e-309

Trả lời

7

này có liên quan đến IEEE754 dấu chấm động định dạng chính nó, không quá nhiều việc thực hiện Python của nó.

Nói chung, phao có thể biểu thị số mũ âm nhỏ hơn số mũ âm lớn, vì denormal numbers. Đây là nơi phần mantissa của phao không còn được giả định ngầm để bắt đầu với một số 1, mà đúng hơn là mô tả toàn bộ mantissa, và bắt đầu bằng số không. Trong trường hợp bạn không biết đó là gì, tôi khuyên bạn nên đọc về cách nổi được đại diện, có lẽ bắt đầu từ here.

Vì điều này, khi bạn đảo ngược một số không chuẩn, bạn có thể kết thúc với số mũ dương quá lớn để đại diện. Máy tính sau đó cung cấp cho bạn inf ở vị trí của nó. Các 1e-308 trong ví dụ của bạn thực sự cũng là không bình thường, nhưng vẫn không nhỏ để tràn khi đảo ngược (vì trong số bình thường, tiêu chuẩn thực sự cho phép tích cực lớn hơn một chút so với số mũ âm).

Trong trường hợp 1e-324, con số đó chỉ đơn giản là quá nhỏ để được biểu diễn ngay cả khi không chính xác, sao cho chữ nổi có hiệu quả bằng không. Đó là lý do tại sao bạn nhận được phân chia bằng không. Hình nổi 64 bit nhỏ nhất có thể biểu diễn (hơi dưới) 5e-324.

+1

Điều này hoàn toàn liên quan đến việc triển khai IEEE 754 của Python. Một ngôn ngữ lập trình sane sẽ cho phép sự phân chia xảy ra (bộ xử lý thực hiện nó một cách chính xác, không giống như các nhà thiết kế Python) và tạo ra kết quả thích hợp. Thay vào đó, Python kiểm tra một cách rõ ràng xem ước số có bằng không và hoạt động khác trong trường hợp này. Điều này có chu kỳ bổ sung, không ngăn chặn tràn xảy ra, và có nghĩa là Python không phải là tuân thủ IEEE 754 (kể từ trong IEEE 754 1.0/0.0 sản xuất + inf). –

+1

@PascalCuoq: Về mặt kỹ thuật, điều đó không hoàn toàn đúng, vì bạn sẽ có ngoại lệ với số học IEEE754 * nếu bạn đã bật bẫy *. Vì đó là xa hành vi mặc định, mặc dù, điểm của bạn là hợp lệ, thừa nhận và đáng chú ý. Tuy nhiên, sự khác biệt giữa hai hành vi được giải thích bởi sự đảo ngược của các biến thể cho phép tràn ra được tạo ra, vì vậy tôi không nghĩ rằng câu trả lời cần phải được cải cách. – Dolda2000

4

giá trị tối thiểu có thể được sử dụng như là numer phao bằng Python là:

2.2250738585072014e-308

Python sử dụng phao nổi đúp chính xác, có thể giữ giá trị từ khoảng 10 đến -308 đến 10 với sức mạnh 308 .

Wikipedia - double precision floating point format

Trên thực tế, có lẽ bạn có thể nhận được số nhỏ hơn 1e-308 qua denormals, Nhưng có một hiệu suất đáng kể hit này. Tôi nhận thấy rằng Python có thể xử lý 1e-324 nhưng gạch dưới trên 1e-325 và trả lại 0.0 làm giá trị.

+0

Cảm ơn bạn, tôi hiểu. Tuy nhiên, tôi không hiểu tại sao chúng ta nhận được 'inf' cho một phạm vi nhỏ và không phải' ZerroDivisionError' như python nên trả về. Nó có thể là một cái gì đó có chủ ý trong thiết kế ngôn ngữ? –

+0

@emartinelli Như tôi đã thử nghiệm '1e-323' không bằng 0 nhưng' 1e-324' bằng 0 trong Python shell đó là lý do tại sao divisionByZero nâng lên. và khi tôi đề cập đến giá trị tối thiểu trong python như float là '2.22e-308' và nhỏ hơn giá trị này, tôi nghĩ Python không thực hiện bất kỳ phép tính toán nào với chúng và chỉ là' try catch' để không tăng lỗi 'dividByZero' – Arman

+1

" * Nhưng có một hiệu suất đáng kể đạt đến điều này * "- Chỉ để ghi lại, điều này không nhất thiết phải đúng. Tôi tin rằng hầu hết các kiến ​​trúc lớn của Intel và AMD đều xử lý các denormals, infinities và NaNs mà không bị phạt thêm. Ngoài ra, nó có lẽ cũng nên nói rằng hình phạt sẽ là khá nhỏ so với hình phạt chạy mã Python giải thích anyway. ;) – Dolda2000

2

Hầu hết mọi thứ đã được giải thích bởi Dolda2000 trong số answer của mình. Tuy nhiên, nó có thể hữu ích cho xem điều này.

>>> 1e-308 
1e-308 
>>> 1e-309 
1e-309 
>>> 1e-323 
1e-323 
>>> 1e-324 
0.0 

Như bạn thấy 1e-324 bằng 0.0 trong việc thực hiện python.Khi Dolda2000 đặt nó rất độc đáo: con số đó chỉ đơn giản là quá nhỏ để được biểu diễn ngay cả khi không chính xác, sao cho chữ nổi có hiệu quả bằng không

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