Количество поплавков между двумя поплавками - PullRequest
10 голосов
/ 28 августа 2010

Скажите, у меня есть два числа с плавающей точкой Python a и b, есть ли простой способ узнать, сколько представимых вещественных чисел находится между двумя в представлении IEEE-754 (или в любом представлении, используемом используемой машиной)?

Ответы [ 4 ]

12 голосов
/ 28 августа 2010

AFAIK, IEEE754 поплавки имеют интересное свойство. Если у вас есть float f, то

(*(int*)&f + 1)

при определенных условиях является следующим представимым числом с плавающей запятой. Так что для поплавков А и В

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

Даст вам количество чисел с плавающей точкой между этими числами.

Для получения дополнительной информации см. http://www.cygnus -software.com /apers / comparingfloats / comparingfloats.htm

10 голосов
/ 28 августа 2010

Я не знаю, для чего вы будете использовать это - но, если оба числа имеют одинаковый показатель степени, это должно быть возможно. Поскольку показатель степени сохраняется в старших разрядах, загрузка байтов с плавающей запятой (в данном случае 8 байтов) в виде целого числа и вычитание одного из другого должна дать желаемое число. Я использую структурную модель для упаковки чисел с плавающей точкой в ​​двоичное представление, а затем распаковываю их как длинные целые (C, 8 байт):

>>> 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
>>>
3 голосов
/ 28 августа 2010

Для положительных чисел b> a> 0 ответ: приблизительно :

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

Есть 52 бита мантиссы (за пределами подразумеваемого 1), умноженного на 2, возведенных в степень.

Таким образом, есть 2 ** 52 числа в диапазоне [1: 2) как в диапазоне [1024: 2048)

0 голосов
/ 28 августа 2010

Я бы посмотрел на функцию frexp в математическом модуле.Пример ниже извлекает мантиссу и преобразует ее в целое число.Разница должна быть числом с плавающей точкой между двумя значениями.

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

Следующий код должен сделать это:

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
>>>
...