Количество поплавков между двумя поплавками

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

Ответ 1

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

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

Ответ 2

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

(*(int*)&f + 1)

при определенных условиях, является следующим представимым числом с плавающей запятой. Итак, для float a и b

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

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

Подробнее см. http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm.

Ответ 3

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

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

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

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

Ответ 4

Я бы посмотрел на функцию 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
>>>