Python的math模块包含诸如floor
&的便捷函数ceil
。这些函数采用浮点数,并在其下或上返回最接近的整数。但是,这些函数将答案作为浮点数返回。例如:
import math
f=math.floor(2.3)
现在f
返回:
2.0
从该浮点数中获取整数而不冒取舍入错误风险的最安全方法是什么(例如,如果浮点数等于1.99999),或者我应该完全使用另一个函数?
Python的math模块包含诸如floor
&的便捷函数ceil
。这些函数采用浮点数,并在其下或上返回最接近的整数。但是,这些函数将答案作为浮点数返回。例如:
import math
f=math.floor(2.3)
现在f
返回:
2.0
从该浮点数中获取整数而不冒取舍入错误风险的最安全方法是什么(例如,如果浮点数等于1.99999),或者我应该完全使用另一个函数?
Answers:
可以用浮点数表示的所有整数均具有精确的表示形式。这样您就可以安全地使用int
结果了。仅当您尝试使用非2的幂的分母来表示有理数时,才会出现不精确的表示。
这项工作一点都不小!IEEE浮点表示的一个属性是int∘floor=⌊⋅⌋,如果所讨论的数字的大小足够小,但是int(floor(2.3))可能为1的情况下,可能会有不同的表示形式。
要引用维基百科,
绝对值小于或等于2 24的任何整数都可以用单精度格式准确表示,绝对值小于或等于2 53的任何整数都可以用双精度格式准确表示。
使用int(your non integer number)
将打钉。
print int(2.3) # "2"
print int(math.sqrt(5)) # "2"
floor
向下int
int(-2.3)
在Python发行版Canopy 2.7.6中进行了测试,并得到了-2
预期的结果。整数可以为负,与正式的Math定义相同。
int(-2.3)
给-2
像你说的,因为它舍入到0
,即最多在这种情况下。相反,最初使用的问题math.floor
总是四舍五入:math.floor(-2.3)
给-3.0
。
math.floor
,并且此答案显示了如何将浮点数转换为整数。math.floor
int
int(math.floor(2.3))
您可以使用舍入功能。如果您不使用第二个参数(有效数字位数),那么我认为您将获得想要的行为。
空闲输出。
>>> round(2.99999999999)
3
>>> round(2.6)
3
>>> round(2.5)
3
>>> round(2.4)
2
round
至少在Python 2.6中也返回一个浮点数。
round
和floor
在Python 3.x的回报整数 所以我想这个问题与Python 2.x有关。
int(round(2.65))
吧?
round(6.5)
给6?ceil()
在所有其他情况下,小数点后立即有5个(或更大的则为9)时,似乎有点浮动。为什么在这种情况下不起作用?或任何其他情况,当数字以6结尾并且在小数点后有5时…
结合之前的两个结果,我们得到:
int(round(some_float))
这可以相当可靠地将浮点数转换为整数。
float
代表一个大于正常值的数字int
。在Python 2中,是否存在float
只能使用long
(四舍五入后)表示的值?
int()
函数根据需要生成一个int
或一个long
...
这项工作一点都不小!IEEE浮点表示的一个属性是int∘floor=⌊⋅⌋,如果所讨论的数字的大小足够小,但是int(floor(2.3))可能为1的情况下,可能会有不同的表示形式。
这篇文章解释了为什么它可以在这个范围内工作。
在double中,您可以毫无问题地表示32位整数。有不能是任何四舍五入问题。更精确地,双精度数可以表示2 53和-2 53之间(包括2 53和-2 53)的所有整数。
简短说明:一个double最多可以存储53个二进制数字。当您需要更多时,该数字将在右边填充零。
由此可见,53个数字是无需填充即可存储的最大数字。自然,所有需要较少数字的(整数)数字都可以准确存储。
将111加1(省略)111(53个)将产生100 ... 000,(53个零)。众所周知,我们可以存储53位数字,即最右边的零填充。
这是2 53的来源。
详细信息:我们需要考虑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位的左侧,可以很容易地看到,任何整数必须具备的所有位尾数为此右上小数点零。
除零以外的任何整数都具有以下二进制形式:
1x ... x,其中x -es表示MSB右侧的位(最高有效位)。
因为我们排除了零,所以总会有一个MSB为1,这就是为什么不存储它的原因。要存储整数,我们必须将其转换为上述形式:-1 符号 ×1.尾数×2 指数偏差。
就是说,将这些位移到小数点后直到只有MSB朝MSB的左侧移动。然后,小数点右边的所有位都存储在尾数中。
由此可见,除MSB外,我们最多可以存储52个二进制数字。
因此,显式存储所有位的最高编号为
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。
它代表2 53,它标志着我们可以准确表示所有整数的边界(负向和正向)。如果要将1加到2 53,则必须将隐式零(由表示x
)设置为1,但这是不可能的。
math.floor
将始终返回整数,因此int(math.floor(some_float))
永远不会引入舍入错误。
但是,舍入错误可能已经引入了math.floor(some_large_float)
,或者甚至当首先将大量存储在float中时也已引入。(存储在浮点数中的大数字可能会失去精度。)
math.floor
在v2.6中返回浮点数,但在v3中返回整数。在这一点上(OP之后将近六年),这个问题可能很少出现。