在python中将float转换为整数的最安全方法?

时间:2010-08-02 12:20:21

标签: python math integer python-2.x

Python的数学模块包含方便的函数,如floor& ceil。这些函数采用浮点数并返回低于或高于它的最接近的整数。但是,这些函数将答案作为浮点数返回。例如:

import math
f=math.floor(2.3)

现在f返回:

2.0

从这个浮点数中获取整数的最安全的方法是什么,而不存在舍入错误的风险(例如,如果浮点数相当于1.99999),或者我应该完全使用另一个函数?

10 个答案:

答案 0 :(得分:154)

可以用浮点数表示的所有整数都有精确的表示。因此,您可以安全地在结果上使用int。仅当您尝试使用不是2的幂的分母来表示有理数时,才会出现不精确的表示。

这项工作并非微不足道!它是IEEE浮点表示的一个属性,如果所讨论的数字的大小足够小,则int∘floor=⌊⋅⌋,但int(floor(2.3))可能为1时可能有不同的表示。

引用Wikipedia

  

绝对值小于或等于2 24 的任何整数都可以用单精度格式精确表示,绝对值小于或等于2 53的任何整数可以用双精度格式精确表示。

答案 1 :(得分:94)

使用int(your non integer number)会钉它。

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

答案 2 :(得分:44)

您可以使用圆形功能。如果你没有使用第二个参数(有效数字的数量),那么我认为你会得到你想要的行为。

IDLE输出。

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

答案 3 :(得分:38)

结合前两个结果,我们有:

int(round(some_float))

这可以相当可靠地将浮点数转换为整数。

答案 4 :(得分:18)

  

这项工作并非微不足道!它是IEEE浮点表示的一个属性,如果所讨论的数字的大小足够小,则int∘floor=⌊⋅⌋,但int(floor(2.3))可能为1时可能有不同的表示。

这篇文章解释了为什么它在该范围内起作用

在double中,您可以毫无问题地表示32位整数。 不能是任何舍入问题。更确切地说,双精度可以表示 2 53 -2 之间的 所有 整数53

简短说明:双精度数最多可存储53个二进制数字。当您需要更多时,数字会在右边用零填充。

接下来,53个是没有填充可以存储的最大数字。当然,所有需要较少数字的(整数)数字都可以准确存储。

111(省略)111 (53个)中添加一个产生100 ... 000,(53个零)。我们知道,我们可以存储53个数字,这使得最右边的零填充。

这是2 53 的来源。


更多细节:我们需要考虑IEEE-754浮点的工作原理。

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

然后按如下方式计算数字(不包括此处无关的特殊情况):

  

-1 sign ×1.mantissa×2 指数 - 偏差

其中 bias = 2 exponent - 1 - 1 ,即1023和127分别为双精度/单精度。

知道乘以 2 X 只需将所有位 X 位置移到左侧,很容易看出任何整数都必须全部尾数中以小数点右边结束的位为零。

除零之外的任何整数都具有以下二进制形式:

  

1x ... x 其中 x -es表示MSB右侧的位(最高位)。

因为我们排除了零,所以总是是一个MSB,这就是为什么它没有存储。要存储整数,我们必须将其变为上述形式: -1 sign ×1.mantissa×2 exponent - bias

这就像将位移到小数点上一样,直到只有MSB左侧的MSB。然后将小数点右侧的所有位存储在尾数中。

由此可以看出,除了MSB,我们最多可以存储52个二进制数字。

下面是显式存储所有位的最高位数

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

为此,我们需要设置指数,使小数点移动52位。如果我们将指数增加1,我们就不能知道小数点后左边的数字。

111(omitted)111x.

按惯例,它是0.将整个尾数设置为零,我们收到以下数字:

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

这是1,然后是53个零,52个存储,1个由于指数而添加。

它表示 2 53 ,它标记了我们可以准确表示所有整数的边界(正面和正面)。如果我们想在 2 53 中添加一个,我们必须将隐式零(由x表示)设置为1,但这是不可能的。< / p>

答案 5 :(得分:6)

math.floor将始终返回一个整数,因此int(math.floor(some_float))将永远不会引入舍入错误。

但是,math.floor(some_large_float)中可能已经引入了舍入错误,或者甚至在首先将大数字存储在浮点数中时也是如此。 (存放在花车中时,大数字可能会失去精度。)

答案 6 :(得分:5)

如果需要将字符串float转换为int,则可以使用此方法。

示例:'38.0'38

为了将其转换为int,您可以将其转换为float,然后转换为int。这也适用于浮点字符串或整数字符串。

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

注意:这将删除小数点后的任何数字。

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

答案 7 :(得分:1)

使用变量将real / float转换为整数的另一个代码示例。 “vel”是一个实数/浮点数并转换为下一个最高的INTEGER,“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))

答案 8 :(得分:0)

由于您正在寻求“最安全”的方式,因此我将提供除最佳答案之外的另一个答案。

确保不损失任何精度的一种简单方法是在转换后检查值是否相等。

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

例如,如果float为1.0,则1.0等于1。因此将执行向int的转换。并且如果float为1.1,则int(1.1)等于1,并且1.1!=1。因此,该值将保持为float,并且不会损失任何精度。

答案 9 :(得分:0)

df ['Column_Name'] = df ['Column_Name']。astype(int)