Как проверить, является ли значение с плавающей точкой целым числом

203

Я пытаюсь найти самый большой корень куба, который является целым числом, которое составляет менее 12 000.

processing = True
n = 12000
while processing:
    n -= 1
    if n ** (1/3) == #checks to see if this has decimals or not

Я не уверен, как проверить, если это целое число или нет! Я мог бы преобразовать его в строку, а затем использовать индексирование, чтобы проверить конечные значения и посмотреть, равны ли они нулю или нет, хотя это кажется довольно громоздким. Есть ли более простой способ?

тяпка ничья lion4
источник
3
было бы легче работать с корнем куба n -> (n * n * n <12000)
подозреваемый

Ответы:

367

Чтобы проверить, является ли значение с плавающей точкой целым числом, используйте float.is_integer()метод :

>>> (1.0).is_integer()
True
>>> (1.555).is_integer()
False

Метод был добавлен в floatтип в Python 2.6.

Учтите, что в Python 2 1/3есть 0(деление по полу для целочисленных операндов!), И что арифметика с плавающей запятой может быть неточной (a float- это приближение, использующее двоичные дроби, а не точное действительное число). Но немного подкорректировав цикл, вы получите:

>>> for n in range(12000, -1, -1):
...     if (n ** (1.0/3)).is_integer():
...         print n
... 
27
8
1
0

Это означает, что что-либо более 3 кубов (включая 10648) было пропущено из-за вышеупомянутой неточности:

>>> (4**3) ** (1.0/3)
3.9999999999999996
>>> 10648 ** (1.0/3)
21.999999999999996

Вместо этого вам придется проверять номера, близкие к целому, или не использовать их float()для поиска своего номера. Как округление корня куба 12000:

>>> int(12000 ** (1.0/3))
22
>>> 22 ** 3
10648

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

>>> from math import isclose
>>> isclose((4**3) ** (1.0/3), 4)
True
>>> isclose(10648 ** (1.0/3), 22)
True

Для более старых версий наивная реализация этой функции (пропуск проверки ошибок и игнорирование бесконечности и NaN), как упомянуто в PEP485 :

def isclose(a, b, rel_tol=1e-9, abs_tol=0.0):
    return abs(a - b) <= max(rel_tol * max(abs(a), abs(b)), abs_tol)
Мартейн Питерс
источник
Не зная Python, такое утверждение заставило бы меня нервничать, поскольку для работы в реальном мире, кажется, требуется идеальная математика.
Питер М
1
@PeterM: метод действительно возвращается, только Trueесли нет десятичных дробей вообще. Конечно, со стороны ОП может быть неправильное понимание арифметики и точности с плавающей запятой.
Мартин Питерс
1
@MartijnPieters Да, и один маленький пробел в вычислении с плавающей запятой, и вдруг у вас появляются эти маленькие, нежелательные десятичные дроби, такие как 0,00000000000000000001
Питер М
1
@PeterM: и в Python 2 представление по умолчанию округляется до 16 цифр; 1.0000000000000001отображается как 1.0, в 3 показано самое короткое строковое представление, которое дает то же значение.
Мартин Питерс
Вы range(12000, -1, -1)могли бы быть (лучше, точнее) переписаны какreversed(range(12000+1))
cs95
36

Мы можем использовать оператор по модулю (%). Это говорит нам, сколько у нас осталось, когда мы делим x на y - выражается как x % y. Каждое целое число должно делиться на 1, поэтому, если есть остаток, он не должен быть целым числом.

Эта функция возвращает логическое значение Trueили False, в зависимости от того, nявляется ли целое число.

def is_whole(n):
    return n % 1 == 0
MagikCow
источник
15

Вы можете использовать это:

if k == int(k):
    print(str(k) + " is a whole number!")
Юри Робл
источник
5
это терпит неудачу для больших чисел, в то время как .is_integer()продолжает работать.
JFS
Ваша ссылка ИМХО не показывает, что она не работает. Это просто показывает, что большие поплавки теряют точность. is_integerиспользует аналогичный метод ( o = (floor(x) == x) ? Py_True : Py_False;). Но я согласен, нужно использовать, так is_integer()как это намного понятнее.
Юри Робл
1
да. Это просто показывает, что большой float может потерять точность, т. large_float == large_intЕ. Может потерпеть неудачу, даже если large_float == float(large_int).
JFS
2
123456789012345678901234567890.0 != 123456789012345678901234567890но123456789012345678901234567890.0 == float(123456789012345678901234567890)
JFS
2
Да, но k = 123456789012345678901234567890.0тогда k == int(k)это правда, что является правильным ответом.
Юри Робл
9

Вам не нужно ничего зацикливать или проверять. Просто возьмите кубический корень из 12 000 и округлите его:

r = int(12000**(1/3.0))
print r*r*r # 10648
Georg
источник
Это разумный ответ.
hughdbrown
7

Вы можете использовать операцию по модулю для этого.

if (n ** (1.0/3)) % 1 != 0:
    print("We have a decimal number here!")
Якуб Джирутка
источник
2
если n6.2, 6.0, 6.12312412, у всех нас есть "We have a decimal number here!"?
Джей Вонг
@JayWong не уверен, как вы загрузили свой тест, но это отлично работает на моей машине, использующей Python3.7.
Зчпывр
6

Не проще ли проверить корни куба? Начните с 20 (20 ** 3 = 8000) и до 30 (30 ** 3 = 27000). Затем вам нужно проверить менее 10 целых чисел.

for i in range(20, 30):
    print("Trying {0}".format(i))
    if i ** 3 > 12000:
        print("Maximum integral cube root less than 12000: {0}".format(i - 1))
        break
hughdbrown
источник
1
Кроме того, числа с плавающей точкой имеют ошибки округления, так что вы можете пропустить число при вычислении, если n**(1/3)целое число. Например, на моем компьютере `10648 ** (1/3) = 21.999999999999996` вместо 22: проблема! С этим методом ответа такой проблемы нет. Я думаю, что это единственно правильное решение с математической точки зрения (другие решения являются Python-правильными).
JPG
5

Как насчет

if x%1==0:
    print "is integer"
Даниил
источник
3

Приведенные выше ответы работают для многих случаев, но они пропускают некоторые. Учтите следующее:

fl = sum([0.1]*10)  # this is 0.9999999999999999, but we want to say it IS an int

Используя это в качестве эталона, некоторые другие предложения не получают желаемого поведения:

fl.is_integer() # False

fl % 1 == 0     # False

Вместо этого попробуйте:

def isclose(a, b, rel_tol=1e-09, abs_tol=0.0):
    return abs(a-b) <= max(rel_tol * max(abs(a), abs(b)), abs_tol)

def is_integer(fl):
    return isclose(fl, round(fl))

теперь мы получаем:

is_integer(fl)   # True

iscloseпоставляется с Python 3.5+ , а для других Python вы можете использовать это в основном эквивалентное определение (как упомянуто в соответствующем PEP )

control_fd
источник
1
math.fsum([0.1] * 10) == 1
Acumenus
1

Просто дополнительная информация, is_integerвнутренне:

import math
isInteger = (math.floor(x) == x)

Не совсем в Python, но реализация cpython реализована, как указано выше.

user1767754
источник
1

Все ответы хороши, но надежный метод огня будет

def whole (n):
     return (n*10)%10==0

Функция возвращает True, если это целое число, иначе False .... Я знаю, что немного опоздал, но вот один из интересных методов, которые я сделал ...

Изменить: как указано в комментарии ниже, более дешевый эквивалентный тест будет:

def whole(n):
    return n%1==0
random_npc
источник
1
Это не должно быть функционально отличным от n % 1 == 0. В этом случае вы выполняете две операции, которые стоят дороже для более дешевого эквивалентного теста.
Зчпывр
0
>>> def is_near_integer(n, precision=8, get_integer=False):
...     if get_integer:
...         return int(round(n, precision))
...     else:
...         return round(n) == round(n, precision)
...
>>> print(is_near_integer(10648 ** (1.0/3)))
True
>>> print(is_near_integer(10648 ** (1.0/3), get_integer=True))
22
>>> for i in [4.9, 5.1, 4.99, 5.01, 4.999, 5.001, 4.9999, 5.0001, 4.99999, 5.000
01, 4.999999, 5.000001]:
...     print(i, is_near_integer(i, 4))
...
4.9 False
5.1 False
4.99 False
5.01 False
4.999 False
5.001 False
4.9999 False
5.0001 False
4.99999 True
5.00001 True
4.999999 True
5.000001 True
>>>
csaszizoltan
источник
Вот несколько рекомендаций о том, как мне написать хороший ответ? , Этот предоставленный ответ может быть правильным, но это могло бы извлечь выгоду из объяснения. Ответы только кода не считаются "хорошими" ответами. Из обзора .
Трентон Маккинни
-1

Попробуйте использовать:

int(val) == val

Это даст намного больше точности, чем любые другие методы.

Нишант Ингл
источник
Можете ли вы привести пример, подтверждающий утверждение, что «это даст гораздо больше точности»? Это кажется необоснованным.
Марк Дикинсон
-1

Вы можете использовать roundфункцию для вычисления значения.

Да, в python, как указывали многие, когда мы вычисляем значение корня куба, он выдаст вам вывод с небольшой ошибкой. Чтобы проверить, является ли значение целым числом, вы можете использовать следующую функцию:

def cube_integer(n):
    if round(n**(1.0/3.0))**3 == n:
        return True
    return False

Но помните, что int(n)это эквивалентно math.floorи из-за этого, если вы найдете, int(41063625**(1.0/3.0))вы получите 344 вместо 345.

Поэтому, пожалуйста, будьте осторожны при использовании intкубических корней.

Anivarth
источник