Увеличьте значение с плавающей запятой Python на минимально возможную величину - PullRequest
59 голосов
/ 19 мая 2011

Я использую значения с плавающей точкой в ​​качестве словарных ключей.

Иногда очень иногда (и, возможно, никогда, но не обязательно никогда), будут конфликты.Я хотел бы разрешить их, увеличив значение с плавающей запятой на минимально возможное значение.Как я могу это сделать?

В C я бы вертел биты мантиссы, чтобы достичь этого, но я предполагаю, что это невозможно в python.

Ответы [ 14 ]

2 голосов
/ 20 мая 2011

Вместо разрешения коллизий путем изменения ключа, как насчет сбора коллизий? IE:

bag = {}
bag[1234.] = 'something'

становится

bag = collections.defaultdict(list)
bag[1234.].append('something')

будет ли это работать?

2 голосов
/ 19 мая 2011

Я думаю, что вы имеете в виду «как можно меньше, чтобы избежать коллизии хэшей», так как, например, следующий наивысший float уже может быть ключом!=)

while toInsert.key in myDict: # assumed to be positive
    toInsert.key *= 1.000000000001
myDict[toInsert.key] = toInsert

При этом вы, вероятно, не хотите использовать метки времени в качестве ключей.

1 голос
/ 24 мая 2011

Взглянув на ответ автопопуля, я придумал немного другой ответ:

import math, sys

def incrementFloatValue(value):
    if value == 0:
        return sys.float_info.min                                
    mant, exponent = math.frexp(value)                                                   
    epsilonAtValue = math.ldexp(1, exponent - sys.float_info.mant_dig)                
    return math.fsum([value, epsilonAtValue])

Отказ от ответственности: я действительно не так хорош в математике, как мне кажется;) Пожалуйста, убедитесь, что это правильно, прежде чем использовать его. Также я не уверен насчет производительности

некоторые заметки:

  • epsilonAtValue вычисляет, сколько битов используется для мантиссы (максимальный минус, что используется для показателя степени).
  • Я не уверен, нужен ли math.fsum(), но эй, похоже, не больно.
0 голосов
/ 23 мая 2011

Оказывается, это на самом деле довольно сложно (может быть, поэтому семь человек ответили, фактически не предоставив ответа…)и положительные значения правильно:

import math
import sys

def incrementFloat(f):
    if f == 0.0:
        return sys.float_info.min
    m, e = math.frexp(f)
    return math.ldexp(m + sys.float_info.epsilon / 2, e)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...