Как сравнить округленное float в python? [dубликат]

У вас нет всех возможностей или возможности доступа к зашифрованным файлам при автоматическом входе в систему, поэтому попробуйте выполнить вход в систему и обратно, и посмотрите, дает ли это вам эти способности. Если это позволяет отключить автоматический вход в систему, то это быстрый способ.

Если это не сработает, загрузитесь с живого CD / DVD или USB-накопителя Ubuntu, откройте Nautilus (т. Е. Браузер файлов ) и щелкните по тому для системы Ubuntu, установленной на вашем жестком диске (она указана в верхней части левой панели любого окна браузера), чтобы установить ее. Затем выйдите из этого оригинального окна Nautilus и нажмите Alt + F2 и запустите gksu nautilus (это открывает окно браузера файлов как root с неограниченными возможностями). В окне браузера файлов, созданным при этом, найдите том, который вы только что установили (вам, возможно, придется вручную просмотреть его внутри /media), и внутри него перейдите в каталог etc. Внутри этого перейдите в каталог lightdm. Сделайте резервную копию файла lightdm.conf, а затем отредактируйте исходный файл, чтобы удалить строку, которая начинается autologin-user=. Затем перезагрузитесь (используя значок питания / шестерни> Shut Down в правом верхнем углу рабочего стола), извлеките CD / DVD или USB-накопитель и загрузитесь в свою установленную систему. Теперь вы должны увидеть экран входа, как вы привыкли.

(В итоге загрузите живую систему и создайте резервную копию и отредактируйте /etc/lightdm/lightdm.conf, чтобы удалить строку autologin-user=.)

191
задан 10 July 2017 в 11:38

8 ответов

Это может быть немного уродливое взломать, но оно работает очень хорошо, когда вам не нужно больше, чем точность поплавка по умолчанию (около 11 десятичных знаков). Хорошо работает на python 2.7.

Функция round_to использует метод format из встроенного класса str для округления float до строки, которая представляет float с количеством десятичных знаков, необходимых, а затем применяет eval встроенная функция для округленной строки с плавающей точкой, чтобы вернуться к числовому типу float.

Функция round_to просто применяет простой условный к округленному поплавку.

def round_to(float_num, decimal_precision):
    return eval("'{:." + str(int(decimal_precision)) + "f}'.format(" + str(float_num) + ")")

def is_close(float_a, float_b, decimal_precision):
    if round_to(float_a, decimal_precision) == round_to(float_b, decimal_precision):
        return True
    return False

a = 10.0 / 3
# Result: 3.3333333333333335
b = 10.0001 / 3
# Result: 3.3333666666666666

print is_close(a, b, decimal_precision=4)
# Result: False

print is_close(a, b, decimal_precision=3)
# Result: True
0
ответ дан 15 August 2018 в 15:52

В некоторых случаях, когда вы можете повлиять на представление исходного номера, вы можете представлять их как фракции вместо float, используя целочисленный числитель и знаменатель. Таким образом, вы можете иметь точные сравнения.

Подробнее см. В разделе «Фракция от фракций».

1
ответ дан 15 August 2018 в 15:52

Я не знаю ничего в стандартной библиотеке Python (или в другом месте), которая реализует функцию AlmostEqual2sComplement Доусона. Если это то поведение, которое вы хотите, вам придется реализовать его самостоятельно. (В этом случае, вместо того, чтобы использовать умные поразрядные хаки Доусона, вам, вероятно, лучше использовать более традиционные тесты формы if abs(a-b) <= eps1*(abs(a)+abs(b)) + eps2 или аналогичные. Чтобы получить поведение Доусона, вы можете сказать что-то вроде if abs(a-b) <= eps*max(EPS,abs(a),abs(b)) для некоторых небольших фиксированных EPS, это не совсем то же самое, что и Доусон, но похоже по духу.

11
ответ дан 15 August 2018 в 15:52
  • 1
    Я не совсем понимаю, что вы здесь делаете, но это интересно. В чем разница между eps, eps1, eps2 и EPS? – Gordon Wrigley 8 April 2011 в 18:19
  • 2
    eps1 и eps2 определяют относительный и абсолютный допуск: вы готовы разрешить a и b отличаться примерно на eps1 раз, насколько они велики плюс eps2. eps - единственный допуск; вы готовы разрешить a и b отличаться примерно на eps раз, насколько они велики, при условии, что размер размера EPS или меньше считается размером EPS. Если вы принимаете EPS как наименьшее не-денормальное значение вашего типа с плавающей точкой, это очень похоже на компаратор Доусона (за исключением коэффициента в 2 ^ # бита, потому что Доусон измеряет допуск в ulps). – Gareth McCaughan 8 April 2011 в 19:22
  • 3
    Кстати, я согласен с С. Лоттом в том, что Right Thing всегда будет зависеть от вашего реального приложения, поэтому нет никакой стандартной библиотечной функции для всех ваших потребностей в сравнении с плавающей точкой. – Gareth McCaughan 8 April 2011 в 19:23
  • 4
    @ gareth-mccaughan Как определить «наименьшее не-денормальное значение вашего типа с плавающей запятой»? для python? – Gordon Wrigley 10 April 2011 в 04:09
  • 5
    На этой странице docs.python.org/tutorial/floatingpoint.html говорится, что почти все реализации python используют поплавки с двойной точностью IEEE-754 и эту страницу en.wikipedia.org/wiki/IEEE_754-1985 [ ! d1] говорит, что нормированные числа, наиболее близкие к нулю, ± 2 ** - 1022. – Gordon Wrigley 10 April 2011 в 04:34

Мне понравилось предложение @Sesquipedal, но с модификацией (специальный прецедент, когда оба значения равны 0, возвращает False). В моем случае я был на Python 2.7 и просто использовал простую функцию:

if f1 ==0 and f2 == 0:
    return True
else:
    return abs(f1-f2) < tol*max(abs(f1),abs(f2))
1
ответ дан 15 August 2018 в 15:52

Использовать модуль decimal Python, который предоставляет класс Decimal.

Из комментариев:

Стоит отметить, что если вы делаете математическую работу и вам не нужна абсолютная точность с десятичной точки, это может действительно утомить вещи. Поплавки - это путь, способ быстрее справляться, но неточный. Десятичные числа являются чрезвычайно точными, но медленными.
11
ответ дан 15 August 2018 в 15:52

Является ли что-то вроде простого недостаточно хорошего?

return abs(f1 - f2) <= allowed_error
53
ответ дан 15 August 2018 в 15:52
  • 1
    Поскольку ссылка, которую я изложил, указывает, что вычитание работает только в том случае, если вы заранее знаете приблизительную величину чисел. – Gordon Wrigley 8 April 2011 в 18:14
  • 2
    @tolomea: Именно поэтому для этого нет стандартной библиотечной функции. Это всегда зависит от реальной проблемы. – S.Lott 8 April 2011 в 18:24
  • 3
    @ S.Lott не идеальное решение для всех обстоятельств, не является веской причиной не предоставлять разумного решения для большинства обстоятельств. Без такого решения конечным пользователям остается использовать любую дерьмо, которую они мечтают сами по себе, например abs (f1 - f2) allowed_error, который терпит неудачу, когда величины f1 и f2 не известны заранее. – Gordon Wrigley 9 April 2011 в 17:22
  • 4
    @tolomea: пожалуйста, не назовите ответы здесь и «дерьмо». Это оскорбительно и ничего не решает. Представьте свой аргумент и продолжайте. – Andrew White 9 April 2011 в 17:58
  • 5
    По моему опыту, лучшим методом сравнения поплавков является: abs(f1-f2) < tol*max(abs(f1),abs(f2)). Такой относительный перенос является единственным значимым способом сравнения поплавков в целом, так как на них обычно влияет ошибка округления в небольших десятичных знаках. – Sesquipedal 4 February 2015 в 05:52

Я нашел следующее сравнение полезным:

str(f1) == str(f2)
27
ответ дан 15 August 2018 в 15:52
  • 1
    numpy.allclose (...) сделает трюк, красиво. – Fred Mitchell 3 February 2014 в 00:43
  • 2
    «Установка numpy может быть нетривиальным опытом в зависимости от вашей платформы.» ... um Что? Какие платформы являются «нетривиальными»? установить numpy? Что именно сделало его нетривиальным? – John 14 November 2014 в 22:36
  • 3
    @John: трудно получить 64-битный двоичный файл для Windows. Трудно получить numpy через pip в Windows. – Ben Bolker 6 March 2015 в 06:05
  • 4
    это интересно, но не очень практично из-за str (.1 + .2) == .3 – Gordon Wrigley 27 May 2015 в 00:06
  • 5
    @Ternak: Да, но некоторые из моих учеников используют Windows, поэтому мне приходится иметь дело с этим. – Ben Bolker 24 November 2015 в 07:34
  • 6
    str (.1 + .2) == str (.3) возвращает True – Henrikh Kantuni 13 March 2016 в 02:38
  • 7
    @BenBolker Если вам нужно установить открытую научную платформу с данными, основанной на Python, лучшим способом будет Anaconda continuum.io/downloads (pandas, numpy и больше из коробки) – jrovegno 28 December 2016 в 00:22
  • 8
    Как это отличается от f1 == f2 - если они близки, но все еще отличаются из-за точности, представления строк также будут неравными. – MrMas 11 January 2017 в 20:43
  • 9
    .1 + .2 == .3 возвращает False, а str (.1 + .2) == str (.3) возвращает True – Kresimir 12 January 2017 в 20:35

math.isclose () добавлен в Python 3.5 для этого (исходный код). Вот его порт на Python 2. Различие между однострочным шрифтом Mark Ransom заключается в том, что он может обрабатывать «inf» и «-inf» правильно.

def isclose(a, b, rel_tol=1e-09, abs_tol=0.0):
    '''
    Python 2 implementation of Python 3.5 math.isclose()
    https://hg.python.org/cpython/file/tip/Modules/mathmodule.c#l1993
    '''
    # sanity check on the inputs
    if rel_tol < 0 or abs_tol < 0:
        raise ValueError("tolerances must be non-negative")

    # short circuit exact equality -- needed to catch two infinities of
    # the same sign. And perhaps speeds things up a bit sometimes.
    if a == b:
        return True

    # This catches the case of two infinities of opposite sign, or
    # one infinity and one finite number. Two infinities of opposite
    # sign would otherwise have an infinite relative tolerance.
    # Two infinities of the same sign are caught by the equality check
    # above.
    if math.isinf(a) or math.isinf(b):
        return False

    # now do the regular computation
    # this is essentially the "weak" test from the Boost library
    diff = math.fabs(b - a)
    result = (((diff <= math.fabs(rel_tol * b)) or
               (diff <= math.fabs(rel_tol * a))) or
              (diff <= abs_tol))
    return result
4
ответ дан 15 August 2018 в 15:52

Другие вопросы по тегам:

Похожие вопросы: