如何强制使除法为浮点数?除法始终向下舍入为0?

784

我有两个整数值 ab,但我需要它们的浮点比率。 我知道 a < b 并且我想计算 a / b,因此如果我使用整数除法,我将始终得到余数为 a 的 0。

在 Python 2 中,以下代码如何强制c成为浮点型数?

c = a / b

在3.x版本中,行为反转;请参阅整数除法为什么产生浮点数而不是另一个整数?以获取相反的3.x特定问题。

11个回答

851
在Python 2中,两个整数相除会得到一个整数,而在Python 3中会得到一个浮点数。我们可以通过从__future__导入相关的模块以获取新的行为。
>>> from __future__ import division
>>> a = 4
>>> b = 6
>>> c = a / b
>>> c
0.66666666666666663

91
如果你选择这条路,并且仍需要一些整数除法,你可以使用 a // b 进行计算。 - Steve Trout
34
请注意,在Python 3中,这是默认行为。 - Sam DeFabbia-Kane
7
这也是 Idle (ipython) shell 中的默认行为,但不适用于 ipython 脚本解释器。当调试由默认系统 python 解释器运行的脚本时,这可能会导致令人头痛的问题。 - hobs
4
不过,这并不会改变operator.div的行为。要做到这一点,可以使用operator.truediv()。 - Caltor
19
请注意,from __future__ import division 必须放在文件的开头。 - yannis
显示剩余2条评论

752

您可以通过执行 c = a / float(b) 来将其转换为浮点数。如果分子或分母是浮点数,则结果也将是浮点数。


注意:正如评论者指出的那样,如果b可能不是整数或浮点数(或表示其中之一的字符串),则此方法将无法正常工作。如果您可能会处理其他类型(例如复数),您需要检查这些类型或使用其他方法。


我会将两个操作数都转换为浮点数,以使代码更清晰。仅转换触发特殊代码路径的一个操作数会让许多人阅读代码感到困惑。你也会陷入Acute所处的情况。 - Charlie
8
使用__future__不是比这个更好的答案。当将b转换为float时,可能会丢失信息!正确的解决方法是通过将另一个乘数乘以1.0来避免这种情况。 - Antti Haapala -- Слава Україні
@AnttiHaapala 是否有特定情况下,强制转换为 float 不起作用但 __future__ 起作用的情况?我期望未来的除法使用与其实现策略相同的方法。而乘以 1.0 和强制转换为 float 有什么不同呢? - Mark Ransom
2
例如,如果转换的参数不是floatint类型,则会失败。正确的方法在PEP 238中详细讨论。 - Antti Haapala -- Слава Україні

210

如何在Python中强制使用浮点数除法?

我有两个整数a和b,但我需要它们的比率为浮点数。我知道a < b,并且我想计算a/b,所以如果我使用整数除法,我将始终得到余数为a的0。

如何在以下情况下在Python中强制将c作为浮点数?

c = a / b
这里实际上正在问:“如何强制进行真除法,以便 a / b 返回一个分数?”

升级至 Python 3

在 Python 3 中,要获取真除法,只需执行 a / b 即可。
>>> 1/2
0.5

整数的经典除法行为——地板除,现在表示为a // b

>>> 1//2
0
>>> 1//2.0
0.0

然而,你可能会被困在使用Python 2的情况下,或者你可能正在编写必须在2和3两个版本中都能运行的代码。

如果使用Python 2

在Python 2中,情况并不那么简单。处理经典的Python 2除法的一些方法比其他方法更好、更稳健。

Python 2的建议

你可以通过在模块顶部导入以下内容来获得任何给定模块中的Python 3除法行为:

from __future__ import division

然后应用Python 3风格的除法到整个模块。它也在任何给定时刻的Python shell中工作。在Python 2中:

>>> from __future__ import division
>>> 1/2
0.5
>>> 1//2
0
>>> 1//2.0
0.0

这真的是最好的解决方案,因为它确保您的模块中的代码更加向前兼容Python 3。

Python 2的其他选项

如果你不想将此应用于整个模块,那么你只有一些变通方法可用。最流行的方法是强制将其中一个操作数转换为浮点数。一个稳健的解决方案是a / (b * 1.0)。在一个新的Python shell中:

>>> 1/(2 * 1.0)
0.5

operator.truediv(a, b) 这个函数调用也很强大,但它可能会更慢一些。

>>> from operator import truediv
>>> truediv(1, 2)
0.5

不建议在Python 2中使用

常见的是a / float(b)。如果b是一个复数,这将引发TypeError。由于使用复数进行除法是有定义的,所以当传递一个复数作为除数时,我认为没有必要让除法失败。

>>> 1 / float(2)
0.5
>>> 1 / float(2j)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can't convert complex to float

故意让你的代码更加脆弱对我来说没有多少意义。

您还可以使用-Qnew标志运行Python,但这样做的缺点是将所有模块都执行为新的Python 3行为,而您的某些模块可能希望使用传统除法,因此我不建议这样做,除非用于测试。但是为了演示:

$ python -Qnew -c 'print 1/2'
0.5
$ python -Qnew -c 'print 1/2j'
-0.5j

4
"1 // 2 = 0","1 // 2.0 = 0.0" —— 这是一个有趣的小陷阱,即使是整数除法,如果任何一个操作数是浮点数,那么结果仍然是整数但也是浮点数。我用整数除法来计算列表索引,因此出现了错误。 - R. Navega
我更喜欢使用 a / (b + 0.0),因为加法通常比乘法更快,即使差异微不足道。 - Mark Ransom

137
c = a / (b * 1.0)

67
在Python 3.x中,单斜杠(/)始终表示真实(非截断)除法。 (//运算符用于截断除法。)在Python 2.x(2.2及以上版本),您可以通过添加 from __future__ import division导入将其设置为相同的行为。
from __future__ import division

在你的模块顶部。


32

只要将除法的任何参数设置为浮点格式,输出结果也将以浮点数格式呈现。

示例:

>>> 4.0/3
1.3333333333333333

或者,

>>> 4 / 3.0
1.3333333333333333
或者,
>>> 4 / float(3)
1.3333333333333333
或者,
>>> float(4) / 3
1.3333333333333333

5
但是你可能会在以后尝试执行1.0 + 1/3float(c) + a/bfloat(a/b)等操作,而且你会对得到的结果感到失望。最好使用Python 3+版本或者导入__future__.division模块(见接受的答案),这样你总能得到你期望的结果。现有的除法规则会创建难以跟踪的暗藏数学错误。 - hobs
@JoeCondron 你试过 python -c 'a=10; b=3.0; print a/b' 吗? - gsbabil
我不需要这样做,因为在这种情况下它显然是有效的。但是,如果ab是整数值函数的输出呢?例如,a = len(list1), b = len(list2) - JoeCondron
@JoeCondron:好观点。我刚刚更新了答案,包括float(..)。我认为像@Pinochle下面建议的那样乘以1.0也可能很有用。 - gsbabil

22

添加一个点(.)表示浮点数

>>> 4/3.
1.3333333333333333

3
如果分子和分母都是变量,你将如何应用这种方法? - stackoverflowuser2010
我假设你指的是第一个例子,如果是这样的话,我会在其中一个变量上使用 float() - Alexander

14

这样也可以运作

>>> u=1./5
>>> print u
0.2

5
如果分子和分母都是变量,你打算如何应用这种方法? - stackoverflowuser2010
1
因为在使用变量进行抽象时它无法工作。几乎没有有意义的代码像那样硬编码数值。 - Keir Simmons
1
这个回答没有回答问题,也不是一个通用的答案,所以得票很少。在回答中,首先展示为什么这个方法有效非常重要。很简单:如果分子或分母是浮点数,结果将是浮点数。通常你不会把Python当作纯文本计算器,所以你需要一个变量ab的答案。 - TimZaman
长久以来,我实际上认为 ./ 是 Python 中一个有效的运算符,可以进行浮点数除法。这就是为什么在任何编程语言中都要明智地使用空格的好处。 - smac89

7

如果您想默认使用“真正的”(浮点数)除法,则有一个命令行标志:

python -Q new foo.py

以下是PEP中提到的一些缺点:

有人认为,通过命令行选项来更改默认值是不好的。在错误的手中,它肯定是危险的:例如,无法将需要“-Qnew”的第三方库包与另一个需要“-Qold”的库包结合使用。

您可以查看Python手册,了解更改/警告除法行为的其他标志值。

有关除法更改的完整详细信息,请阅读:PEP 238 -- 更改除法运算符


2
from operator import truediv

c = truediv(a, b)

2
不过,这并不理想,因为它不能处理 a 是整数而 b 是浮点数的情况。更好的解决方案是按照相同的思路执行 from operator import truediv,然后使用 truediv(a, b) - Mark Dickinson
是的,你说得对。我假设两个整数,因为这是除法操作不同的唯一情况,但你确实想要一个通用解决方案。我实际上并不知道你可以导入运算符或者它对于浮点数除数根本不起作用。回答已编辑。 - JoeCondron

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接