Самый безопасный способ конвертировать float в integer в python?



математический модуль Python содержит удобные функции, такие как floor & ceil. Эти функции принимают число с плавающей запятой и возвращает ближайшее целое число ниже или выше его. Однако эти функции возвращают ответ в виде числа с плавающей запятой. Например:



import math
f=math.floor(2.3)


теперь f возвращает:



2.0


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

848   9  

9 ответов:

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

что это работает совсем не тривиально! Это свойство представления с плавающей запятой IEEE, что int floor floor = ⌊ ⋅ ⌋ если величина рассматриваемых чисел достаточно мала, но отличается представления возможны там, где int(floor(2.3)) может быть 1.

цитата из Википедия,

любое целое число с абсолютным значением меньше или равным 224 может быть точно представлен в формате одной точности, и любое целое число с абсолютным значением меньше или равно 253 может быть точно представлено в формате двойной точности.

использовать int(your non integer number) сделают это.

print int(2.3) # "2"
print int(math.sqrt(5)) # "2"

вы можете использовать функцию round. Если вы не используете второй параметр (#значащих цифр), то я думаю, что вы получите поведение, которое вы хотите.

холостой выход.

>>> round(2.99999999999)
3
>>> round(2.6)
3
>>> round(2.5)
3
>>> round(2.4)
2

объединив два предыдущих результата, мы имеем:

int(round(some_float))

это преобразование float в целое число довольно надежно.

что это работает совсем не тривиально! Это свойство представления с плавающей запятой IEEE, что int∘floor = ⌊ ⋅ ⌋ если величина рассматриваемых чисел достаточно мала, но возможны различные представления, где int(Floor(2.3)) может быть 1.

этот пост объясняет, почему он работает в этом диапазоне.

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

краткое описание: двойной может хранить до 53 двоичных цифр. Когда вам требуется больше, число дополняется нулями справа.

из этого следует, что 53 единицы-это наибольшее число, которое может быть сохранено без заполнения. Естественно, все (целочисленные) числа, требующие меньше цифр, могут быть сохранены точно.

добавление одного к 111 (опущено) 111 (53 единицы) дает 100...000, (53 нулями). Как мы знаем, мы можем хранить 53 цифры, что делает самое правое нулевое заполнение.

вот где 253 происходит от.


более подробно: мы должны рассмотреть, как работает IEEE-754 с плавающей запятой.

  1 bit    11 / 8     52 / 23      # bits double/single precision
[ sign |  exponent | mantissa ]

затем число вычисляется следующим образом (исключая особые случаи, которые здесь неуместны):

-1знак × 1.×мантиссы 2степень - смещение

здесь уклон = 2экспонента - 1 - 1, т. е. 1023 и 127 для двойной/одинарной точности соответственно.

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

любое целое число, кроме нуля имеет следующий вид в двоичном виде:

1x...x здесь x - es представляют биты справа от MSB (самый значительный бит).

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

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

из этого мы видим, что мы можем хранить не более 52 двоичных цифр, кроме MSB.

отсюда следует, что наибольшее число где все биты явно хранятся это

111(omitted)111.   that's 53 ones (52 + implicit 1) in the case of doubles.

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

111(omitted)111x.

по соглашению, это 0. Установив всю мантиссу на ноль, получаем следующее число:

100(omitted)00x. = 100(omitted)000.

это 1, за которым следуют 53 нуля, 52 сохраненных и 1 добавленный из-за показатель.

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

math.floor всегда будет возвращать целое число, и таким образом int(math.floor(some_float)) никогда не будет вводить ошибки округления.

ошибка округления уже может быть введена в math.floor(some_large_float), хотя, или даже при хранении большого числа в поплавке в первую очередь. (Большие числа могут потерять точность при хранении в поплавках.)

другой пример кода для преобразования реального / float в целое число с помощью переменных. "Вэл" реальная/число с плавающей точкой и преобразуется до следующего наибольшего целого числа, "newvel".

import arcpy.math, os, sys, arcpy.da
.
.
with arcpy.da.SearchCursor(densifybkp,[floseg,vel,Length]) as cursor:
 for row in cursor:
    curvel = float(row[1])
    newvel = int(math.ceil(curvel))

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

пример: '38.0' до 38

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

>>> int(float('38.0'))
38
>>> int(float('38'))
38

Примечание: это будет лишить любые числа после десятичного знака.

>>> int(float('38.2'))
38

поскольку вы просите "самый безопасный" способ, я дам другой ответ, кроме верхнего ответа.

простой способ убедиться, что вы не потеряете точность, - это проверить, будут ли значения равны после их преобразования.

if int(some_value) == some_value:
     some_value = int(some_value)

если поплавок равен 1,0, например, 1,0 равно 1. Таким образом, преобразование в int будет выполняться. И если поплавок равен 1.1, int (1.1) приравнивается к 1 и 1.1 != 1. Таким образом, значение останется плавающим, и вы не потеряете ни одного точность.

Comments

    Ничего не найдено.