2010-01-16 23 views
8

Gần đây, một phóng viên được đề cập float.as_integer_ratio(), mới trong Python 2.6, lưu ý rằng việc triển khai điểm nổi điển hình về cơ bản là xấp xỉ số thực. Tò mò, tôi đã phải cố gắng π:Hạn chế thực hiện của float.as_integer_ratio()

>>> float.as_integer_ratio(math.pi); 
(884279719003555L, 281474976710656L) 

Tôi đã nhẹ ngạc nhiên không thấy càng accurate kết quả do Arima,:

(428224593349304L, 136308121570117L) 

Ví dụ, mã này:

#! /usr/bin/env python 
from decimal import * 
getcontext().prec = 36 
print "python: ",Decimal(884279719003555)/Decimal(281474976710656) 
print "Arima: ",Decimal(428224593349304)/Decimal(136308121570117) 
print "Wiki: 3.14159265358979323846264338327950288" 

sản xuất kết quả này:

 
python: 3.14159265358979311599796346854418516 
Arima: 3.14159265358979323846264338327569743 
Wiki: 3.14159265358979323846264338327950288 

Chắc chắn, kết quả là chính xác với độ chính xác được cung cấp bởi số dấu phẩy động 64 bit, nhưng nó dẫn tôi hỏi: Làm thế nào tôi có thể tìm hiểu thêm về các giới hạn triển khai của as_integer_ratio()? Cảm ơn bạn đã hướng dẫn.

Liên kết bổ sung: Stern-Brocot treePython source.

+2

Câu trả lời được chấp nhận là gây hiểu lầm. Phương thức 'as_integer_ratio' trả về tử số và mẫu số của một phân số có giá trị _exactly_ khớp với giá trị của số dấu phẩy động được truyền cho nó. Nếu bạn muốn một biểu diễn chính xác hoàn toàn của float của bạn như một phần nhỏ, sử dụng 'as_integer_ratio'. Nếu bạn muốn một _approximation_ đơn giản hóa với mẫu số nhỏ hơn và tử số, hãy nhìn vào 'fractions.Fraction.limit_denominator'. IOW, 'math.pi' là xấp xỉ π. Nhưng '884279719003555/281474976710656' là _not_ một xấp xỉ với' math.pi'; nó là _exactly_ bằng với nó. –

+0

@MarkDickinson: Quan điểm của bạn được thực hiện tốt; nó làm rõ [câu trả lời liên quan] này (https://stackoverflow.com/a/2076903/230513). Mặc dù [câu trả lời được chấp nhận] (https://stackoverflow.com/a/2076296/230513) có thể sử dụng một số bảo trì, nó đã giúp tôi nhìn thấy nơi mà suy nghĩ của tôi đã biến mất. – trashgod

Trả lời

3

Thuật toán được sử dụng bởi as_integer_ratio chỉ considers powers of 2 in the denominator. Đây là (có thể) better algorithm.

+0

Aha, '281474976710656 = 2^48'. Bây giờ tôi thấy các giá trị đến từ đâu. Thú vị so sánh việc triển khai: http: //svn.python.org/view/python/trunk/Objects/floatobject.c? revision = 77139 & view = markup – trashgod

+6

Nói thuật toán không chính xác là một lời giải thích sai lầm. 'float.as_integer_ratio()' đơn giản trả về cho bạn một cặp (tử số, mẫu số) * bằng * số lượng dấu phẩy động trong câu hỏi (đó là lý do tại sao mẫu số là lũy thừa của hai số, vì các số dấu phẩy động tiêu chuẩn có số mũ cơ số 2). Sự mất chính xác đến từ bản thân biểu diễn dấu phẩy động, * không * từ float.as_integer_ratio() mà thực sự là mất mát. –

+0

IIUC, thuật toán đủ chính xác cho độ chính xác của dấu phẩy động đã cho. Nguồn gốc của mẫu số là điều làm tôi bối rối. Thuật toán sẽ không bao giờ tạo ra kết quả độc đáo của Arima, và sẽ không có điểm nào cho độ chính xác được yêu cầu. – trashgod

1

Đi qua kho lưu trữ nguồn cho Python, tìm hiểu ai đã cam kết mã quan tâm và gửi chúng ra khỏi email.

3

Tôi có thể khuyên gmpy 's thi hành Stern-Brocot tree:

>>> import gmpy 
>>> import math 
>>> gmpy.mpq(math.pi) 
mpq(245850922,78256779) 
>>> x=_ 
>>> float(x) 
3.1415926535897931 
>>> 

một lần nữa, kết quả là "đúng trong phạm vi chính xác của nổi 64-bit" (53-bit "cái gọi là" mantissas; -), nhưng:

>>> 245850922 + 78256779 
324107701 
>>> 884279719003555 + 281474976710656 
1165754695714211L 
>>> 428224593349304L + 136308121570117 
564532714919421L 

... chính xác gmpy của thu được rất nhiều rẻ (về tổng của tử số và mẫu số giá trị) so với Arima của, ít hơn nhiều Python 2.6 của -)

! 363.210
+0

Tôi thấy lợi ích. Tôi đã sử dụng GMP từ Ada trước, do đó, 'gmpy' sẽ có ích. http://code.google.com/p/adabindinggmpmpfr/ – trashgod

3

Bạn nhận được xấp xỉ tốt hơn sử dụng

fractions.Fraction.from_float(math.pi).limit_denominator() 

phân số có từ có lẽ phiên bản 3.0. Tuy nhiên, math.pi không có đủ độ chính xác để trả về xấp xỉ 30 chữ số.

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