2015-06-10 68 views
8

Trong khi lập trình, tôi nhận thấy sự khác biệt giữa kết quả của math.exp (2) và math.e ** 2. Như bạn có thể thấy dưới đây, sự khác biệt này không phát sinh khi tính e^1.Sự khác biệt giữa math.exp (2) và math.e ** 2

Không phải là một lập trình viên có kinh nghiệm, tôi tự hỏi tại sao điều này lại khác biệt? Tôi cho rằng nó có liên quan đến việc làm tròn. Tài liệu trăn nói rằng math.exp(x) trả lại e**x, nhưng điều này dường như không chính xác. Vậy hoạt động của math.exp(x) khác với math.e**x như thế nào?

>>> math.exp(1) 
2.718281828459045 
>>> math.e**1 
2.718281828459045 
>>> math.exp(1)==math.e**1 
True 
>>> math.exp(2) 
7.38905609893065 
>>> math.e**2 
7.3890560989306495 
>>> math.exp(2)==math.e**2 
False 
>>> math.exp(100) 
2.6881171418161356e+43 
>>> math.e**100 
2.6881171418161212e+43 
>>> math.exp(100)==math.e**100 
False 
+2

Related: http://stackoverflow.com/a/15322395/1639625 Đoán của tôi: 'math.exp' được thực hiện trong' c' (hoặc thậm chí trong phần cứng) và do đó có hành vi điểm nổi hơi khác nhau. –

+1

Bỏ phiếu để mở lại. Có nhiều điều xảy ra ở đây hơn là chỉ đơn giản là "dấu phẩy động là không chính xác". Đặc biệt, khi hai câu trả lời giải thích, có những lý do tốt để mong đợi 'exp (x)' chính xác hơn 'e ** x'. –

Trả lời

4

Điều này khác nhau do sự khác biệt trong việc thực hiện các chức năng. Không ai là hoàn hảo do bản chất của điểm nổi.

Toán tử ** được triển khai trong floatobject.c và chứa rất nhiều trường hợp đặc biệt, nhưng không có trường hợp nào được gọi ở đây, vì vậy cuối cùng nó đạt đến hàm C pow chuẩn. Chức năng math.pow cuối cùng cũng giống như vậy.

Chức năng exp là một trình bao bọc đơn giản xung quanh hàm C cùng tên, được xác định bằng macro trong mathmodule.c.

Khi điều đó xảy ra, điểm kinh nghiệm chính xác hơn (cả hai kết quả khớp với độ chính xác cho phép bằng dấu phẩy động, các câu trả lời chính xác cao tôi tính bằng bc). Nhiều khả năng đó là vì trong nội bộ để pow, nó được tính toán logarit mở rộng có độ chính xác của giá trị tăng gấp đôi độ chính xác e bạn vượt qua như là đối số đầu tiên, đó là hơi nhỏ hơn 1.


Vấn đề cơ bản là math.e, đó là số bạn đang tính toán sức mạnh của, là:

2.718281828459045 09079559829... 

trong khi giá trị thực của e

2.718281828459045 23536028747... 

Và lỗi này phức tạp khi bạn sử dụng pow hoặc **, trong khi nó có thể không (hoặc có thể sử dụng giá trị chính xác cao hơn trong nội bộ) nếu bạn đang sử dụng exp do chi tiết của thuật toán sử dụng.

+0

Đối với sự hiểu biết của tôi: bc là gì? – oscarwhiskybravo

+0

@ rosie2go Đây là một máy tính dòng lệnh chính xác tùy ý cho các hệ thống Unix và Unix - vì nó chính xác tùy ý tôi có thể đặt nó thành 50 chữ số và so sánh kết quả đó với kết quả float python. – Random832

+0

Vì vậy, số nguyên 1 trở thành 0.9999999999999999468198834395860075119344401173293590545654296875 khi bạn thay đổi số nguyên thành phao? – oscarwhiskybravo

5

exp(x) được triển khai ở mức thấp hơn nhiều so với e**x. Về cơ bản nó là một trình bao bọc cho một hàm trong libc. Hàm được cho là có thể (ở một mức nào đó) sử dụng việc mở rộng Taylor series để tính giá trị trực tiếp (hoặc có thể là một số phương pháp toán học khác, tôi không chắc chắn).

Mặt khác, e**x đang lấy một số và nâng nó lên một sức mạnh. Đây là một chiến lược hoàn toàn khác và có lẽ ít chính xác hơn trong hầu hết các trường hợp. Việc nâng số lên quyền hạn rất khó để làm chính xác.

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