Проверка того, является ли float эквивалентом целочисленного значения в python

В Python 3 я проверяю, является ли заданное значение треугольным, т. Е. Оно может быть представлено как n (n + 1) / 2 для некоторого натурального n

Могу ли я просто написать:

import math def is_triangular1(x): num=(1/2) * (math.sqrt(8*x+1)-1 ) return int(num)==num 

Или мне нужно сделать это так? :

 epsilon = 0.000000000001 def is_triangular2(x): num=(1/2) * (math.sqrt(8*x+1)-1 ) return abs(int(num) - num)<epsilon 

Я проверил, что обе функции возвращают одинаковые результаты для х до 1 000 000. Но я не уверен, что, вообще говоря, int (x) == x всегда будет правильно определять, является ли число целым, из-за случаев, когда пример 5 представлен как 4.99999999999997 и т. Д.

Насколько я знаю, второй способ правильный, если я делаю это на C, но я не уверен в Python 3.

10 Solutions collect form web for “Проверка того, является ли float эквивалентом целочисленного значения в python”

Вы захотите сделать последнее. В Программе на Python 3 приведен пример, как наиболее точный способ сравнения

 def equal_float(a, b): #return abs(a - b) <= sys.float_info.epsilon return abs(a - b) <= chosen_value #see edit below for more info 

Кроме того, поскольку epsilon – это «самая маленькая разница, машина может различать два числа с плавающей запятой», вы захотите использовать <= в своей функции.

Редактирование : после прочтения комментариев ниже я оглянулся на книгу, и в ней конкретно говорится: «Вот простая функция для сравнения поплавков для равенства с пределом точности машин». Я считаю, что это был всего лишь пример для сопоставления поплавков с предельной точностью, но тот факт, что ошибка введена во многих вычислениях с плавающей запятой, это редко бывает когда-либо использоваться. Я охарактеризовал его как «самый точный» способ сравнения в моем ответе, который в некотором смысле является истинным, но редко, что предполагается при сравнении поплавков или целых чисел с плавающими. Выбор значения (например: 0,00000000001) на основе «проблемного домена» функции вместо использования sys.float_info.epsilon – правильный подход.

Спасибо С.Лотту и Свен Марнах за их исправления, и я прошу прощения, если я привел кого-то по неправильному пути.

Существует функция is_integer в типе float python:

 >>> float(1.0).is_integer() True >>> float(1.001).is_integer() False >>> 

У ваших реализаций есть проблемы. На самом деле может случиться так, что вы получите что-то вроде 4.999999999999997 , поэтому использование функции int() не является опцией.

Я бы выбрал совершенно другой подход: сначала предположим, что ваш номер треугольный, и вычислите, что n будет в этом случае. На этом первом шаге вы можете объединиться щедро, так как нужно только получить результат правильно, если число фактически треугольное. Затем вычислим n * (n + 1) / 2 для этого n и сравним результат с x . Теперь вы сравниваете два целых числа, поэтому никаких неточностей осталось.

Вычисление n можно упростить путем расширения

 (1/2) * (math.sqrt(8*x+1)-1) = math.sqrt(2 * x + 0.25) - 0.5 

и использование этого

 round(y - 0.5) = int(y) 

для положительного y .

 def is_triangular(x): n = int(math.sqrt(2 * x)) return x == n * (n + 1) / 2 

Python имеет Decimal класс (в decimal модуле ), который вы можете использовать, чтобы избежать неточности поплавков.

floats может точно представлять все целые числа в своем диапазоне – равенство с плавающей запятой является только сложным, если вы заботитесь о бит после точки. Итак, пока все вычисления в вашей формуле возвращают целые числа для интересующих вас случаев, int (num) == num совершенно безопасен.

Итак, нам нужно доказать, что для любого треугольного числа каждый кусочек математики, который вы делаете, может выполняться с помощью целочисленной арифметики (и все, что выходит как нецелое число, должно означать, что x не является треугольным):

Для начала мы можем предположить, что x должно быть целым числом – это требуется в определении «треугольного числа».

В этом случае 8 * x + 1 также будет целым числом, так как целые числа будут закрыты относительно + и *.

math.sqrt () возвращает float; но если х треугольно, то квадратный корень будет целым числом, т. е. снова точно представленным.

Итак, для всех x, которые должны возвращать true в ваших функциях, int (num) == num будет true, и поэтому ваш istriangular1 всегда будет работать. Единственным моментом, который упоминается в комментариях к вопросу, является то, что Python 2 по умолчанию выполняет целочисленное деление так же, как C – int / int => int, усекает, если результат не может быть представлен точно как int , Итак, 1/2 == 0. Это исправлено в Python 3, или с помощью строки

 from __future__ import division 

в верхней части вашего кода.

Я думаю, что модуль десятичный – это то, что вам нужно

Вы можете округлить свой номер до 14 знаков после запятой или меньше:

  >>> round(4.999999999999997, 14) 5.0 

PS: двойная точность составляет около 15 знаков после запятой

Трудно спорить со стандартами.

В C99 и POSIX стандартом для округления float к int является параметр nearint () . Важным понятием является направление округления и стандартное соглашение о округлении.

Предполагая, что соглашение является общим округлением , это то же самое, что и соглашение C99 в Python:

 #!/usr/bin/python import math infinity = math.ldexp(1.0, 1023) * 2 def nearbyint(x): """returns the nearest int as the C99 standard would""" # handle NaN if x!=x: return x if x >= infinity: return infinity if x <= -infinity: return -infinity if x==0.0: return x return math.floor(x + 0.5) 

Если вы хотите больше контролировать округление, подумайте об использовании модуля Decimal и выберите соглашение округления, которое вы хотите использовать. Например, вы можете использовать Rounding Banker .

После того, как вы определили соглашение, округлите до int и сравните с другим int.

Python по-прежнему использует одно и то же представление с плавающей запятой и операции C, поэтому второй правильный путь.

Под капотом поплавок типа Python является двойным.

Наиболее надежным способом было бы получить ближайшее целое число до num, а затем проверить, удовлетворяют ли эти целые значения следующему свойству:

 import math def is_triangular1(x): num = (1/2) * (math.sqrt(8*x+1)-1 ) inum = int(round(num)) return inum*(inum+1) == 2*x # This line uses only integer arithmetic 
  • Правильный способ эмулировать одинаковую точку с плавающей запятой в python?
  • Почему sys.maxint <(sys.maxint - 100 + 0.01) в Python?
  • сравнение неравенства float (в python)
  • Вопрос Python об экспонентах и ​​int
  • Печать поплавков с определенным количеством нулей
  • возможно ли найти случайные поплавки в диапазоне в python?
  • Двоичное представление float в Python (бит не hex)
  • python float to in int conversion
  • Python - лучший язык программирования в мире.