2015-09-03 15 views
14

Tôi hiện đang kinh ngạc hơn này:chính xác sự khác biệt khi in Python và C++ đôi

C++ 11

#include <iostream> 
#include <iomanip> 
#include <limits> 

int main() 
{ 
    double d = 1.305195828773568; 
    std::cout << std::setprecision(std::numeric_limits<double>::max_digits10) << d << std::endl; 
    // Prints 1.3051958287735681 
} 

Python

>>> repr(1.305195828773568) 
'1.305195828773568' 

gì đang xảy ra, tại sao thêm 1 trong C++?

Cho đến nay tôi nghĩ rằng C++ và Python sử dụng cùng một IEEE 64 bit đôi dưới mui xe; cả hai chức năng định dạng có nghĩa vụ phải in chính xác đầy đủ.

+1

Lưu ý rằng * thuộc tính * của 'repr' là: 'eval (repr (x)) == x' ** không ** số đó được in với tất cả các chữ số thập phân. Nếu bạn muốn có độ chính xác của chữ số thập phân 'k', bạn nên sử dụng một hàm định dạng thích hợp. – Bakuriu

Trả lời

2

Taken từ một câu trả lời cho this question:

IEEE 754 điểm nổi được thực hiện trong hệ nhị phân. Không có chuyển đổi chính xác từ số bit đã cho đến số chữ số thập phân đã cho. 3 bit có thể giữ các giá trị từ 0 đến 7 và 4 bit có thể giữ các giá trị từ 0 đến 15. Giá trị từ 0 đến 9 mất khoảng 3,5 bit, nhưng điều đó cũng không chính xác.

Số chính xác gấp đôi IEEE 754 chiếm 64 bit. Trong số này, 52 bit được dành riêng cho significand (phần còn lại là bit dấu và số mũ). Kể từ khi significand là (thường) bình thường hóa, có một bit 53 ngụ ý.

Bây giờ, với 53 bit và khoảng 3,5 bit cho mỗi chữ số, phân chia đơn giản cung cấp cho chúng tôi 15.1429 chữ số chính xác. Nhưng hãy nhớ rằng, 3,5 bit trên một chữ số thập phân chỉ là một xấp xỉ, không phải là một câu trả lời hoàn toàn chính xác.

này lạ .1429 sau 15 chữ số mà bạn cung cấp có lẽ là thủ phạm của gia tăng 1.

Đối với những gì nó có giá trị, Python này đã viết trên trang web của họ:

Trong lịch sử, Lời nhắc Python và được xây dựng trong chức năng repr() sẽ chọn một với 17 chữ số có nghĩa, 0,10000000000000001. Bắt đầu với Python 3.1, Python (trên hầu hết các hệ thống) bây giờ có thể chọn ngắn nhất trong số này và chỉ cần hiển thị 0.1.

10

bạn có thể buộc python để in ra 1 là tốt (và nhiều hơn nữa của các chữ số sau):

print('{:.16f}'.format(1.305195828773568)) 
# -> 1.3051958287735681 

từ https://docs.python.org/2/tutorial/floatingpoint.html:

>>> 7205759403792794 * 10**30 // 2**56 
100000000000000005551115123125L 

Trong các phiên bản trước Python 2.7 và Python 3.1, Python làm tròn giá trị này thành 17 chữ số có nghĩa, cho '0.10000000000000001'. Trong phiên bản hiện tại, Python hiển thị giá trị dựa trên phần thập phân ngắn nhất làm tròn lại chính xác giá trị nhị phân thực, kết quả chỉ đơn giản là trong '0,1'.

"in chính xác đầy đủ" khó thực hiện: độ chính xác đầy đủ là bao nhiêu?đại diện của phao là nhị phân; chỉ phân số quyền hạn của 2 có thể được biểu diễn chính xác (với độ chính xác đầy đủ); hầu hết các phân số thập phân không thể được biểu diễn chính xác trong cơ sở 2.

nhưng phao trong bộ nhớ sẽ giống nhau đối với python và C++; nó chỉ là biểu diễn chuỗi khác nhau.

+0

"hầu hết các phân số thập phân không thể được biểu diễn chính xác trong cơ số 2" - có, nhưng ngược lại không đúng. Tất cả các phân số nhị phân có thể biểu diễn bằng số thập phân. Vì vậy, nó sẽ có thể để có được đại diện thập phân chính xác. – n0rd

+0

@ n0rd Đúng. Nhược điểm duy nhất là nó sẽ là một đại diện khá dài và có lẽ không đại diện cho đầu vào thực tế mà từ đó phao nhị phân thu được. –

+2

Giá trị chính xác của số dấu phẩy động nhị phân IEEE 64 bit gần nhất là 1.3051958287735681008001620284630917012691497802734375 - chắc chắn không đại diện cho đầu vào thực tế. –

3

Khi định dạng kết thúc bằng ký hiệu điểm cố định, số precision() chỉ định số chữ số thập phân. Vì có thêm một số không phân số trong ví dụ của bạn nhiều hơn số có thể được biểu diễn một cách an toàn được tạo.

Khi sử dụng ký pháp khoa học, tổng số chữ số được tính và bạn sẽ nhận được các chữ số giống với số nguyên gốc (cộng với số mũ, tất nhiên). Các tùy chọn C và C++ để định dạng các số dấu phẩy động thực sự khá tệ. Đặc biệt, không có tùy chọn cho phép trình định dạng quyết định số chữ số thích hợp mặc dù thuật toán cơ bản thực sự có thể xác định được các số này.

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