我该如何在Python中将一个数字四舍五入到小数点后第二位?例如:
0.022499999999999999
应该四舍五入到0.03
0.1111111111111000
应该向上舍入为0.12
如果第三位小数有任何值,我希望它总是向上舍入,使我保留小数点后两位。
我该如何在Python中将一个数字四舍五入到小数点后第二位?例如:
0.022499999999999999
应该四舍五入到0.03
0.1111111111111000
应该向上舍入为0.12
如果第三位小数有任何值,我希望它总是向上舍入,使我保留小数点后两位。
Python 包括 round()
函数,允许你指定 你想要的小数位数。来自文档:
round(x[, n])
返回四舍五入到小数点后 n 位的浮点数 x。如果省略了 n,则默认为零。结果是一个浮点数。值被四舍五入到最接近的10的负n次幂的倍数;如果两个倍数距离一样,舍入会远离0(例如,round(0.5) 是 1.0,round(-0.5) 是 -1.0)。
因此,您需要使用 round(x, 2)
进行普通舍入。要确保始终向上舍入数字,您需要使用 ceil(x)
函数。同样,要向下舍入,请使用 floor(x)
。
ceil
的代码会意味着抄袭你的答案,所以我将我的留在原样并点赞你的回答。 - simchonafrom math import ceil
num = 0.1111111111000
num = ceil(num * 100) / 100.0
参见:
math.ceil
文档
round
文档 - 无论如何,您将来可能也需要查看此文档。
round()
-- 它不会以任何方式改变结果。 - Sven Marnachmath.ceil((1.11 * 100.0)) / 100.0
结果为 1.12
原因是:
1.11 * 100.0
的值为 111.00000000000001
- nimeshkiranvermaround()
才能获得所需的结果:math.ceil(round(1.11 * 100.0)) / 100.0
。 - Sean Beardenx = math.ceil(x * 100.0) / 100.0
更新的答案:
正如@jpm在评论中指出的那样,我原来的答案存在边界问题。 Python 3 更加困难,因为它使用“银��家”舍入而不是“老派”的四舍五入。然而,在研究这个问题时,我发现了一个更好的解决方案,使用 decimal
库。
import decimal
def round_up(x, place=0):
context = decimal.getcontext()
# get the original setting so we can put it back when we're done
original_rounding = context.rounding
# change context to act like ceil()
context.rounding = decimal.ROUND_CEILING
rounded = round(decimal.Decimal(str(x)), place)
context.rounding = original_rounding
return float(rounded)
或者如果你真的只想要一行代码:
import decimal
decimal.getcontext().rounding = decimal.ROUND_CEILING
# here's the one-liner
float(round(decimal.Decimal(str(0.1111)), ndigits=2))
>> 0.12
# Note: this only affects the rounding of `Decimal`
round(0.1111, ndigits=2)
>> 0.11
以下是一些示例:
round_up(0.022499999999999999, 2)
>> 0.03
round_up(0.1111111111111000, 2)
>> 0.12
round_up(0.1111111111111000, 3)
>> 0.112
round_up(3.4)
>> 4.0
# @jpm - boundaries do what we want
round_up(0.1, 2)
>> 0.1
round_up(1.1, 2)
>> 1.1
# Note: this still rounds toward `inf`, not "away from zero"
round_up(2.049, 2)
>> 2.05
round_up(-2.0449, 2)
>> -2.04
我们还可以使用它来对小数点左侧进行四舍五入:
round_up(11, -1)
>> 20
我们不乘以10,从而避免了这个答案中提到的溢出问题。
round_up(1.01e308, -307)
>> 1.1e+308
原始回答(不建议使用):round(x + 0.005, 2)
或者更加花哨一点:
def round_up(x, place):
return round(x + 5 * 10**(-1 * (place + 1)), place)
这似乎也可以如下运作:
round(144, -1)
# 140
round_up(144, -1)
# 150
round_up(1e308, -307)
# 1.1e308
round(0.1 + 0.005, 2) == 0.11
,而 round(1.1 + 0.005, 2) == 1.10
。 - jpm参考 Edwin 的回答来推断:
from math import ceil, floor
def float_round(num, places = 0, direction = floor):
return direction(num * (10**places)) / float(10**places)
使用方法:
>>> float_round(0.21111, 3, ceil) #round up
>>> 0.212
>>> float_round(0.21111, 3) #round down
>>> 0.211
>>> float_round(0.21111, 3, round) #round naturally
>>> 0.211
math.ceil((1.11 * 100.0)) / 100.0
的结果为 1.12
原因是:
1.11 * 100.0
的值为 111.00000000000001
- nimeshkiranvermaceil(num * 100) / 100
的技巧在某些特殊输入下会崩溃,例如1e308。虽然这种情况可能不经常出现,但我可以告诉你,它让我浪费了几天时间。为了避免这种情况,“如果” ceil()
和 floor()
带有类似于 round()
的小数位参数会很好...同时,有人知道一个干净的替代方法,它不会在这样的输入上崩溃吗?我对 decimal
包也有一些希望,但它似乎也无法正常工作:>>> from math import ceil
>>> from decimal import Decimal, ROUND_DOWN, ROUND_UP
>>> num = 0.1111111111000
>>> ceil(num * 100) / 100
0.12
>>> float(Decimal(num).quantize(Decimal('.01'), rounding=ROUND_UP))
0.12
>>> num = 1e308
>>> ceil(num * 100) / 100
Traceback (most recent call last):
File "<string>", line 301, in runcode
File "<interactive input>", line 1, in <module>
OverflowError: cannot convert float infinity to integer
>>> float(Decimal(num).quantize(Decimal('.01'), rounding=ROUND_UP))
Traceback (most recent call last):
File "<string>", line 301, in runcode
File "<interactive input>", line 1, in <module>
decimal.InvalidOperation: [<class 'decimal.InvalidOperation'>]
当然,有人可能会说,在这种输入情况下崩溃是唯一明智的行为,但我认为造成问题的不是四舍五入,而是乘法(这就是为什么1e306不会崩溃),因此更干净的实现四舍五入到第N位的函数可以避免乘法的hack。
Decimal
的过程中遇到的问题是量化表达式的结果需要311位数字来表达,而当前精度太小。如果您事先执行from decimal import getcontext; getcontext().prec = 400
,这将“起作用”,对于某些值有效。或者您可以注意到,绝对值大于$2^{52}$的任何浮点数必须已经是整数,因此四舍五入不会产生任何影响。是的,我同意如果“ceil”和“floor”带有小数位参数会更好。 - Mark DickinsonPython中的round
函数可能会对你期望的进行不同的四舍五入。
你可以通过使用Decimal.quantize
来更具体地指定四舍五入方法。
例如:
Original Answer
翻译成“最初的回答”。
from decimal import Decimal, ROUND_HALF_UP
res = Decimal('0.25').quantize(Decimal('0.0'), rounding=ROUND_HALF_UP)
print(res)
# prints 0.3
更多参考资料:
https://gist.github.com/jackiekazil/6201722
最初的回答:
这里有一个更通用的一行代码,适用于任何数字:
import math
def ceil(number, digits) -> float: return math.ceil((10.0 ** digits) * number) / (10.0 ** digits)
示例用法:
>>> ceil(1.111111, 2)
1.12
注意:正如nimeshkiranverma所述:
>>> ceil(1.11, 2)
1.12 #Because: 1.11 * 100.0 has value 111.00000000000001
def round_up(number, ndigits=None):
# start by just rounding the number, as sometimes this rounds it up
result = round(number, ndigits if ndigits else 0)
if result < number:
# whoops, the number was rounded down instead, so correct for that
if ndigits:
# use the type of number provided, e.g. float, decimal, fraction
Numerical = type(number)
# add the digit 1 in the correct decimal place
result += Numerical(10) ** -ndigits
# may need to be tweaked slightly if the addition was inexact
result = round(result, ndigits)
else:
result += 1 # same as 10 ** -0 for precision of zero digits
return result
assert round_up(0.022499999999999999, 2) == 0.03
assert round_up(0.1111111111111000, 2) == 0.12
assert round_up(1.11, 2) == 1.11
assert round_up(1e308, 2) == 1e308
我写了一个简单的函数来进行向上取整:
def round_up(number: float, ndigits: int):
offset = 0.5
if ndigits and ndigits > 0:
offset = offset / (10 ** ndigits)
return round(number + offset, ndigits)
else:
return round(number+offset)