Câu trả lời:
Bạn vẫn có thể nhận các giá trị không phải là số (NaN) từ số học đơn giản liên quan đến inf
:
>>> 0 * float("inf")
nan
Lưu ý rằng thông thường bạn sẽ không nhận được inf
giá trị thông qua các phép tính số học thông thường:
>>> 2.0**2
4.0
>>> _**2
16.0
>>> _**2
256.0
>>> _**2
65536.0
>>> _**2
4294967296.0
>>> _**2
1.8446744073709552e+19
>>> _**2
3.4028236692093846e+38
>>> _**2
1.157920892373162e+77
>>> _**2
1.3407807929942597e+154
>>> _**2
Traceback (most recent call last):
File "<stdin>", line 1, in ?
OverflowError: (34, 'Numerical result out of range')
Các inf
giá trị được coi là một giá trị rất đặc biệt với ngữ nghĩa không bình thường, vì vậy nó là tốt hơn để biết về một OverflowError
ngay lập tức thông qua một ngoại lệ, chứ không phải có một inf
giá trị âm thầm tiêm vào tính toán của bạn.
**
có vẻ như một lỗi. Khi nó tràn ra với các số thực, nó sẽ báo lỗi, nhưng khi bất kỳ toán hạng nào của nó là inf
hoặc -inf
, nó sẽ trả về 0.0
hoặc inf
. Vì vậy, nó không làm việc một cách chính xác khi đầu vào là inifinty, nhưng không phải khi kết quả nên vô cùng.
Việc triển khai của Python tuân theo tiêu chuẩn IEEE-754 khá tốt, bạn có thể sử dụng như một hướng dẫn, nhưng nó phụ thuộc vào hệ thống cơ bản mà nó được biên dịch, do đó có thể xảy ra sự khác biệt về nền tảng . Gần đây, một bản sửa lỗi đã được áp dụng cho phép "vô cực" cũng như "inf" , nhưng đó là tầm quan trọng nhỏ ở đây.
Các phần sau đây cũng áp dụng tốt cho bất kỳ ngôn ngữ nào thực hiện chính xác số học dấu phẩy động của IEEE, nó không dành riêng cho Python.
Khi giao dịch với vô cực và lớn hơn >
hoặc nhỏ hơn <
toán tử, các giá trị sau:
+inf
cao hơn-inf
-inf
thấp hơn+inf
+inf
là không cao cũng không thấp hơn+inf
-inf
không cao hơn cũng không thấp hơn -inf
NaN
là sai ( inf
không cao hơn, cũng không thấp hơn NaN
)Khi so sánh cho bình đẳng, +inf
và +inf
bằng nhau, như là -inf
và -inf
. Đây là một vấn đề gây tranh cãi và có thể gây tranh cãi với bạn, nhưng đó là trong tiêu chuẩn IEEE và Python hành xử giống như vậy.
Tất nhiên, +inf
là không đồng đều -inf
và tất cả mọi thứ, bao gồm cả NaN
chính nó, là không đồng đều NaN
.
Hầu hết các phép tính với vô cực sẽ mang lại vô hạn, trừ khi cả hai toán hạng là vô cực, khi phân chia thao tác hoặc modulo, hoặc nhân với số 0, có một số quy tắc đặc biệt cần ghi nhớ:
NaN
0.0
hoặc -0.0
².NaN
.inf - inf
, kết quả không xác định : NaN
;inf - -inf
, kết quả là inf
;-inf - inf
, kết quả là -inf
;-inf - -inf
, kết quả không xác định : NaN
.inf + inf
, kết quả là inf
;inf + -inf
, kết quả không xác định : NaN
;-inf + inf
, kết quả không xác định : NaN
;-inf + -inf
, kết quả là -inf
.math.pow
, pow
hoặc **
là khó khăn, vì nó không hoạt động như bình thường. Nó đưa ra một ngoại lệ tràn khi kết quả có hai số thực quá cao để phù hợp với số float chính xác kép (nó sẽ trả về vô cực), nhưng khi đầu vào là inf
hoặc -inf
, nó sẽ hoạt động chính xác và trả về inf
hoặc 0.0
. Khi đối số thứ hai là NaN
, nó trả về NaN
, trừ khi đối số thứ nhất là 1.0
. Có nhiều vấn đề hơn, không phải tất cả được đề cập trong các tài liệu .math.exp
chịu những vấn đề tương tự như math.pow
. Một giải pháp để khắc phục điều này cho tràn là sử dụng mã tương tự như sau:
try:
res = math.exp(420000)
except OverflowError:
res = float('inf')
Lưu ý 1: như một cảnh báo bổ sung, như được xác định bởi tiêu chuẩn IEEE, nếu kết quả tính toán của bạn dưới hoặc tràn, kết quả sẽ không phải là lỗi dưới hoặc tràn, mà là vô cực dương hoặc âm: 1e308 * 10.0
mang lại inf
.
Lưu ý 2: bởi vì bất kỳ phép tính nào có NaN
trả về NaN
và bất kỳ so sánh nào NaN
, kể cả NaN
chính nó false
, bạn nên sử dụng math.isnan
hàm để xác định xem một số có thực sự không NaN
.
Lưu ý 3: mặc dù Python hỗ trợ viết float('-NaN')
, nhưng dấu hiệu bị bỏ qua, vì không tồn tại dấu hiệu NaN
bên trong. Nếu bạn chia -inf / +inf
, kết quả là NaN
, không -NaN
(không có điều đó).
Lưu ý 4: hãy cẩn thận dựa vào bất kỳ điều nào ở trên, vì Python dựa vào thư viện C hoặc Java mà nó được biên dịch và không phải tất cả các hệ thống cơ bản đều thực hiện chính xác tất cả hành vi này. Nếu bạn muốn chắc chắn, hãy kiểm tra vô hạn trước khi thực hiện các tính toán của bạn.
¹) Gần đây có nghĩa là từ phiên bản 3.2 .
²) Điểm nổi hỗ trợ số 0 dương và âm, vì vậy: x / float('inf')
giữ nguyên dấu hiệu và -1 / float('inf')
sản lượng -0.0
, 1 / float(-inf)
sản lượng -0.0
, 1 / float('inf')
sản lượng 0.0
và -1/ float(-inf)
sản lượng 0.0
. Ngoài ra, 0.0 == -0.0
làtrue
, bạn phải kiểm tra thủ công dấu hiệu nếu bạn không muốn nó là sự thật.
-1 * float('infinity') == -inf
C99 cũng vậy .
Biểu diễn điểm nổi IEEE 754 được sử dụng bởi tất cả các bộ xử lý hiện đại có một số mẫu bit đặc biệt dành riêng cho vô cực dương (dấu = 0, exp = ~ 0, frac = 0), vô cực âm (dấu = 1, exp = ~ 0, frac = 0 ) và nhiều NaN (Không phải là Số: exp = ~ 0, frac ≠ 0).
Tất cả những gì bạn cần lo lắng: một số số học có thể gây ra ngoại lệ / bẫy dấu phẩy động, nhưng chúng không bị giới hạn chỉ với các hằng số "thú vị" này.
OverflowError
.
Tôi tìm thấy một cảnh báo mà cho đến nay không ai đề cập đến. Tôi không biết liệu nó có xuất hiện thường xuyên trong các tình huống thực tế không, nhưng ở đây là vì sự hoàn thiện.
Thông thường, việc tính toán một số vô cực modulo sẽ trả về chính nó như một số float, nhưng một phần vô cực modulo sẽ trả về nan
(không phải là một số). Đây là một ví dụ:
>>> from fractions import Fraction
>>> from math import inf
>>> 3 % inf
3.0
>>> 3.5 % inf
3.5
>>> Fraction('1/3') % inf
nan
Tôi đã gửi một vấn đề trên trình theo dõi lỗi Python. Nó có thể được nhìn thấy tại https://bugs.python.org/su32968 .
Cập nhật: điều này sẽ được sửa trong Python 3.8 .
MỘT CUỘC CÁCH MẠNG RẤT RẤT: Division by Zero
trong một 1/x
phân số, tùy thuộc vào x = 1e-323
nó inf
nhưng khi x = 1e-324
hay ít nó némZeroDivisionError
>>> 1/1e-323
inf
>>> 1/1e-324
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ZeroDivisionError: float division by zero
vì vậy hãy thận trọng
1e309
sẽ được hiểu là+inf
và-1e309
sẽ được hiểu là-inf
.