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

Python的数学模块包含方便的函数,如floor &ceil。这些函数接受一个浮点数,并返回该浮点数下面或上面最接近的整数。然而,这些函数以浮点数的形式返回答案。例如:

import math
f=math.floor(2.3)

现在f返回:

2.0

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

782181 次浏览

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

不过,舍入错误可能已经在math.floor(some_large_float)中引入,甚至在首先将一个大数字存储在浮点数中时也会引入。(较大的数字在浮点数中存储时可能会失去精度。)

所有可以用浮点数表示的整数都有精确的表示法。所以你可以安全地对结果使用int。只有当您试图表示一个分母不是2的幂的有理数时,才会出现不精确的表示。

这是不琐碎的工作在所有!IEEE浮点表表法的一个性质是:int(floor(2.3))的大小足够小,那么int(floor(2.3)) =⌊⌋。但在不同的情况下,int(floor(2.3))可能是1。

引用维基百科

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

你可以使用round函数。如果您不使用第二个参数(有效数字#),那么我认为您将得到您想要的行为。

闲置的输出。

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

使用int(your non integer number)将解决它。

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

这是不琐碎的工作在所有!IEEE浮点表表法的一个性质是:int(floor(2.3))的大小足够小,那么int(floor(2.3)) =⌊⌋。但在不同的情况下,int(floor(2.3))可能是1。

这篇文章解释了为什么它在这个范围内有效

在double类型中,可以毫无问题地表示32位整数。有不能的任何舍入问题。更准确地说,双精度变量可以表示包含2 <一口> 53 > < /晚餐2 <一口> 53 > < /晚餐之间的< em > < / em >整数。

简短的解释: double类型最多可以存储53位二进制数字。当您需要更多时,数字在右侧用零填充。

由此可见,53个1是在没有填充的情况下可以存储的最大数字。自然地,所有需要较少数字的(整数)数字都可以被准确地存储。

将1加到111 111(省略)(53个one)得到100…000(53个0)。我们知道,我们可以存储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分别用于双精度/单精度。

知道乘以2 <一口> X < / >共舞,只是将所有X位的位向左移动,很容易看出任何整数必须有尾数中的所有位在小数点的右边为零。

除0以外的任何整数在二进制中都有以下形式:

1 x……,其中x-es表示MSB(最高有效位)右侧的位。

因为我们排除了0,所以总是将是一个MSB,它是1,这就是为什么它没有被存储。要存储整数,必须将其转换为前面提到的形式:1 <一口> < /迹象一口>报;1.尾数×2指数-偏差

也就是说小数点上移位直到只有MSB往左。小数点右边的所有位都存储在尾数中。

从这里,我们可以看到,除了MSB,我们最多可以存储52个二进制数字。

因此,所有显式存储的位的最大值为

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

为此,我们需要设置指数,这样小数点将移动52位。如果我们要把指数加1,我们就不知道小数点后从右到左的数字。

111(omitted)111x.

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

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

1后面跟着53个0,52个存起来,1个加起来。

它表示2 <一口> 53 > < /晚餐,它标记了边界(负数和正数),在这个边界之间我们可以准确地表示所有整数。如果我们想给2 <一口> 53 > < /晚餐加上1,我们必须将隐式0(由x表示)设为1,但这是不可能的。

结合前面的两个结果,我们得到:

int(round(some_float))

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

另一个使用变量将实数/浮点数转换为整数的代码示例。

.

.

.

.

.

.
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))

如果需要将字符串浮点数转换为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。所以这个值仍然是浮点数,你不会失去任何精度。