2010-08-27 38 views
10

Giả sử tôi có hai phao Python ab, có cách dễ dàng để tìm ra số lượng thực có thể đại diện giữa hai số trong đại diện IEEE-754 hay không.)?Số phao giữa hai phao

+1

Chỉ cần ra khỏi tò mò, những gì bạn cần thông tin này không? –

+0

Ý của bạn là gì? Hai phao nổi cụ thể hoặc nói chung? Và bạn có muốn làm điều này từ python hay bạn muốn thực hiện các phép tính theo cách thủ công? – terminus

+0

Tôi muốn so sánh hai số dấu phẩy động để xác định xem chúng có bằng với độ chính xác gần bằng nhưng không bằng với độ chính xác của biểu diễn hay không. Tôi quan tâm đến việc này trong Python. Xem hàm AlmostEqual2sComplement tại http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm - Tôi biết tôi có thể làm điều đó với những thứ như (ab)/a astrofrog

Trả lời

10

tôi don'tknow những gì bạn sẽ sử dụng này cho - nhưng, nếu cả hai nổi có cùng một số mũ, nó sẽ là có thể. Khi số mũ được giữ trên các bit thứ tự cao, tải các byte float (8 byte trong trường hợp này) như là một số nguyên và trừ đi một số nguyên từ một số khác sẽ cho số bạn muốn. Tôi sử dụng mô hình cấu trúc để đóng gói các phao nổi để biểu diễn nhị phân, và sau đó giải nén những người như (C, 8 byte) ints dài:

>>> import struct 
>>> a = struct.pack("dd", 1.000000,1.000001) 
>>> b = struct.unpack("ll",a) 
>>> b[1] - b[0] 
4503599627 
>>> a = struct.pack("dd", 1.000000000,1.000000001) 
>>> b = struct.unpack("ll",a) 
>>> b[1] - b[0] 
4503600 
>>> 
+0

chỉ ra số mũ không quan trọng, nhưng ký hiệu không. –

+3

+1; câu trả lời hay. Nó sẽ không làm việc trên các hệ thống với một 32-bit C dài, mặc dù. Để ở bên an toàn, hãy sử dụng "

+0

Để hoàn tất, bạn cũng có thể đề cập rằng giải pháp này chỉ hoạt động đối với các định dạng IEEE 754. Trong thực tế, đó không phải là một hạn chế, mặc dù --- rất khó để tìm thấy Python đang chạy trên một nền tảng sử dụng không tăng gấp đôi IEEE 754. –

3

Đối với số dương b> a> 0, câu trả lời là khoảng:

(2**52) ** (log(b,2) - log(a,2)) 

Có 52 bit của mantissa (quá khứ ngụ ý 1), nhân với 2 nâng lên một số mũ.

Vì vậy, có 2 ** 52 con số trong khoảng [1: 2) như trong phạm vi [1024: 2048)

+0

Các teory là tốt - nhưng nó không làm việc cho tôi khi các số phao quá gần. Có thể do thực tế là tính toán nhật ký giới thiệu một số làm tròn chính nó. – jsbueno

12

AFAIK, IEEE754 nổi có một đặc tính thú vị. Nếu bạn có phao f, thì

(*(int*)&f + 1) 

trong các điều kiện nhất định, là số dấu phẩy động biểu diễn tiếp theo. Vì vậy, đối với phao a và b

*(int*)&a - *(int*)&b 

Sẽ cung cấp cho bạn số lượng dấu phẩy động giữa các số đó.

Xem http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm để biết thêm thông tin.

+6

Yêu cầu duy nhất là họ có cùng một dấu hiệu, và không phải là Nan hoặc inf. –

+0

Có vẻ như đó là câu trả lời * cho câu hỏi, nhưng một phần bị thiếu: làm cách nào để thực hiện điều đó trong Python? – Bolo

+0

Trong khi điều này không trả lời câu hỏi cho Python, đây là một câu trả lời rất hay. Sách giáo khoa của tôi về "Phương pháp tính toán" cũng đồng ý với điều này. Bất kỳ ai cũng biết cách chuyển đổi sang Python? – Dragontamer5788

0

Tôi sẽ xem xét hàm frexp trong mô-đun toán học. Ví dụ dưới đây trích xuất phần định trị và chuyển đổi nó thành một số nguyên. Sự khác biệt phải là số lượng nổi giữa hai giá trị.

>>> math.frexp(1.1234567890)[0] * 2**53 
5059599576307254.0 
>>> math.frexp(1.12345678901)[0] * 2**53 
5059599576352290.0 

Các mã sau đây nên làm điều đó:

import math 
import sys 

def delta(x,y): 
    '''Return the number of floats between x and y.''' 
    x = float(x) 
    y = float(y) 
    if x == y: 
     return 0 
    elif x < y: 
     return -delta(y,x) 
    else: 
     x_mant, x_exp = math.frexp(x) 
     y_mant, y_exp = math.frexp(y) 
     x_int = int(x_mant * 2**(sys.float_info.mant_dig + x_exp - y_exp)) 
     y_int = int(y_mant * 2**sys.float_info.mant_dig) 
     return x_int - y_int 

print(delta(1.123456789, 1.1234567889999)) 
450 
>>>