Набор чисел с плавающей точкой

1

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

a =  set([1, 2, 3])

если я добавлю элемент 1.00001 с допуском 1e-4, результирующий набор должен быть

{1, 2, 3}

и не

{1, 1.00001, 2, 3}
  • 0
    Звучит сложно, если вы хотите, чтобы это было эффективно, и вы не хотите, чтобы установленные элементы округлялись. Может быть, определить подкласс float, с помощью специальных методов сравнения или, по крайней мере, пользовательский метод __hash__ .
  • 3
    Эта операция не очень хорошо определена, так как два числа a и c могут быть достаточно далеко друг от друга, чтобы они не считались «равными», но были достаточно близки, чтобы b можно было считать равным любому из них. Добавление одинаковых номеров к наборам в разных порядках может привести к разным результатам. Математически отношение эквивалентности должно быть транзитивным и нарушать его, что приведет к плохому поведению. Создание подобных кладж для чисел с плавающей запятой, как правило, плохой дизайн.
Теги:
floating-point
set
compare

3 ответа

5
Лучший ответ

Мы можем использовать круглую функцию для проверки tolerance of 1e-4

a = set([1,2,3])
def add(number):
  if(round(number,4) not in a):
    a.add(number)


add(1)
print(a)
add(1.0000)
print(a)
add(1.0001)
print(a)
add(1.1)
print(a)
4

Мне кажется, вы должны просто проверить каждый элемент уже в наборе, и если абсолютная разница между этим элементом и тем, который вы пытаетесь добавить, меньше порога, просто не добавляйте его.

Что-то вроде этого должно сделать трюк:

def AddToSetWithThreshold(pSet, pValue, pThreshold):
    vList = [entry for entry in pSet if abs(pValue - entry) < pThreshold]
    if len(vList) == 0:
        pSet.add(pValue)

a = set([1, 2, 3]) ; print(a)
AddToSetWithThreshold(a, 1.00001, 1e-4) ; print(a)
AddToSetWithThreshold(a, 1.00001, 1e-6) ; print(a)

Поскольку первое добавление слишком близко к 1 а второе - нет, это приведет к следующему результату:

set([1, 2, 3])
set([1, 2, 3])
set([1, 2, 3, 1.00001])
0

импортировать математику и использовать ceil

import math

decimals = 3

v = 1.234566789
print(math.ceil(v*pow(10,decimals))/pow(10,decimals))  
# 1.234

или если вы хотите, чтобы intger как "порог" просто использовал

print(float(int(v)))
# 1.0
  • 0
    Это выглядит довольно сложно и медленнее, чем при использовании round .

Ещё вопросы

Сообщество Overcoder
Наверх
Меню