如何使用Python保留两位小数?

629

我在这段代码(华氏度转摄氏度转换器)的输出中得到了很多小数。

我的代码目前看起来像这样:

def main():
    printC(formeln(typeHere()))

def typeHere():
    global Fahrenheit
    try:
        Fahrenheit = int(raw_input("Hi! Enter Fahrenheit value, and get it in Celsius!\n"))
    except ValueError:
        print "\nYour insertion was not a digit!"
        print "We've put your Fahrenheit value to 50!"
        Fahrenheit = 50
    return Fahrenheit

def formeln(c):
    Celsius = (Fahrenheit - 32.00) * 5.00/9.00
    return Celsius

def printC(answer):
    answer = str(answer)
    print "\nYour Celsius value is " + answer + " C.\n"



main()

那么我的问题是,我该如何使程序将每个答案四舍五入到小数点后第2位?


11
关于你的代码,有一个小注释。没有必要将华氏温度值作为全局变量保存,将其作为参数传递到函数中就足够了(而且更好)。因此,请删除 "global Fahrenheit" 行。 在 formeln 函数中,将参数名称改为函数 "Fahrenheit",即 formeln(Fahrenheit)。 至于舍入,您只需使用 "%" 参数来仅显示前两位数字,并且应对这些数字进行舍入。在 formeln 中提供的公式中,提供的数字位数不会受到影响。 - arieli
21个回答

1028
你可以使用round函数,它的第一个参数是数字,第二个参数是小数点后的精度。
在你的情况下,代码应该是这样的:
answer = str(round(answer, 2))

58
【注意】对于浮点数,round()函数的行为可能会让人感到惊讶:例如,round(2.675, 2)会返回2.67而不是预期的2.68 - johnsyweb
83
我不确定是什么原因让人们点赞了上面的评论。记录一下,round(2.675, 2)得出的结果是2.67而不是2.68,这与银行家舍入法没有任何关系。 - Mark Dickinson
5
请注意:这将更改答案的值。如果您只是想四舍五入以供显示,请使用@Johnsyweb的答案-https://dev59.com/xmIj5IYBdhLWcg3wPzDH#20457284 - hardmooth
10
@Johnsyweb,我今天尝试了一下,这是原始帖子发布后的几年,看起来它的运行效果符合预期。似乎round()函数随着时间的推移有所改进。请参见以下内容: round(1.379, 2) -> 1.38 round(1.372, 2) -> 1.37 round(1.375, 2) -> 1.38 - NightFurry
4
round(2.675,2)的结果是2.67,因为浮点数的本质使得2.675在计算机中无法精确表示。通过运行from decimal import Decimal; Decimal.from_float(2.675),你可以发现2.675实际上被存储成了2.67499999999999982236431605997495353221893310546875。我发现这个链接很有用。 - aruku7230
显示剩余5条评论

209

使用 str.format()语法显示保留两位小数的answer(不改变answer的基本值):

def printC(answer):
    print("\nYour Celsius value is {:0.2f}ºC.\n".format(answer))

其中:

  • :引入了格式规范
  • 0启用数字类型的符号感知零填充
  • .2精度设置为2
  • f以定点数形式显示数字

4
在我看来,这是最有用的回答 - 保持实际价值不变且容易实现!谢谢! - BrettJ
5
为什么不可以呢?0.5357比0.53更接近0.54,因此将其四舍五入为0.54是有道理的。 - ShadowRanger
1
@Janothan 浮点数值不是精确的。尝试使用"{:0.20f}".format(1.755),你会看到为什么带有两位小数的值显示为1.75 - Matthias
1
这里的符号感知零填充是什么意思?我知道如果数字不够长,它将用前导零进行填充,但由于这里没有最小长度要求(如{:05.2f}),那么这个零是做什么用的? - Jack
3
距离我写下这个回答已经过去了6.5年(和许多Python版本),我忘记为什么觉得把零包含在内是值得的。 - johnsyweb
显示剩余3条评论

91

大多数答案建议使用round或者format。然而round有时会向上舍入,在我的情况下我需要将变量的向下舍入而不仅仅是显示为这样。

round(2.357, 2)  # -> 2.36

我在这里找到了答案:如何将浮点数四舍五入到特定的小数位?

import math
v = 2.357
print(math.ceil(v*100)/100)  # -> 2.36
print(math.floor(v*100)/100)  # -> 2.35
或者:
from math import floor, ceil

def roundDown(n, d=8):
    d = int('1' + ('0' * d))
    return floor(n * d) / d

def roundUp(n, d=8):
    d = int('1' + ('0' * d))
    return ceil(n * d) / d

2
"将值舍入到最接近10的负ndigits次幂的倍数;https://docs.python.org/3/library/functions.html#round因此,round并不总是向上舍入,例如:`round(2.354, 2) # -> 2.35`" - Pete Kirkham
@PeteKirkham 你说得对,我编辑了我的答案以使其更有意义和准确。 - s4w3d0ff
好的,你应该用负值检查你的解决方案... math.floor(0.5357706100)/100 -> 0.53 math.floor(-0.5357706100)/100 -> -0.54 - Noam Peled
3
对于将-0.5357706舍入到小数点后两位的正确答案是-0.54,因为它是一个负数,-0.54比-0.53小。 - s4w3d0ff
6
我会使用10**d代替int('1' + ('0' * d)) - Jonathon Reinhart

66

如果你只想要将四舍五入的结果打印出来,你可以使用自 Python 3.6 开始引入的f-strings。语法与str.format()格式化字符串语法相同,只需在字面字符串前加上一个f,并直接在大括号中放置变量即可。

.2f表示保留两位小数:

number = 3.1415926
print(f"The number rounded to two decimal places is {number:.2f}")

输出:

The number rounded to two decimal places is 3.14

1
这将把39.555四舍五入为39.55,如果您期望四舍五入为39.56,则会得到不正确的结果。 - martin36
2
如果任何人在.2之后不加上f,那么像14.426599999999999这样的数字将会四舍五入为1.4e+01。就Python 3.8.6而言。 - carloswm85
1
@martin36,这不是错误的结果,因为39.555不能在浮点格式中被精确地表示,所以Python实际上会存储数字39.554999999999999....,这个数字被正确地四舍五入为39.55。如果有人期望它被舍入到39.56,那么我认为这种期望是错误的。当使用浮点数时,您应该意识到这些“不准确性”,并且要么接受它们,要么选择不同的数据类型。 - wovano

65

你可以使用round函数。

round(80.23456, 3)

将会给你一个80.234的答案

在您的情况下,请使用

answer = str(round(answer, 2))

21

你想要对答案进行四舍五入处理。

round(value,significantDigit) 是通常用来完成此操作的解决方案,但是当你要四舍五入到一个数字左边(更小)的数字刚好为 5 的情况下,它有时无法从数学角度按照人们预期的方式进行操作。

以下是一些不可预测行为的示例:

>>> round(1.0005,3)
1.0
>>> round(2.0005,3)
2.001
>>> round(3.0005,3)
3.001
>>> round(4.0005,3)
4.0
>>> round(1.005,2)
1.0
>>> round(5.005,2)
5.0
>>> round(6.005,2)
6.0
>>> round(7.005,2)
7.0
>>> round(3.005,2)
3.0
>>> round(8.005,2)
8.01
假设您的意图是在科学统计中进行传统舍入,这是一个便捷的包装器,可使 round 函数按预期工作,而无需像 Decimal 一样 import 额外的内容。
>>> round(0.075,2)

0.07

>>> round(0.075+10**(-2*6),2)

0.08

啊哈!所以基于这个,我们可以制作一个函数...

def roundTraditional(val,digits):
   return round(val+10**(-len(str(val))-1), digits)

基本上,这会在使用 round 函数时遇到无法正常舍入的情况下,将一个非常小的值添加到字符串中,以强制其正确舍入。建议添加的值为 1e-X,其中X是您正在尝试使用 round 舍入的数字字符串的长度加上 1

使用 10**(-len(val)-1) 的方法是故意的,因为它是可以添加的最大小数,同时确保即使缺少小数点符号.,添加的值也永远不会改变舍入方式。我可以只使用 10**(-len(val)) 并带有条件语句 if (val>1) 来减去更多的 1,但总体来说,始终减去 1 更简单,因为这不会显著改变此解决方法适用的十进制数范围。如果您的值达到类型的限制,则该方法将失败,但对于几乎所有有效的十进制值范围,它应该都能正常工作。

因此,最终代码将类似于:

def main():
    printC(formeln(typeHere()))

def roundTraditional(val,digits):
    return round(val+10**(-len(str(val))-1))

def typeHere():
    global Fahrenheit
    try:
        Fahrenheit = int(raw_input("Hi! Enter Fahrenheit value, and get it in Celsius!\n"))
    except ValueError:
        print "\nYour insertion was not a digit!"
        print "We've put your Fahrenheit value to 50!"
        Fahrenheit = 50
    return Fahrenheit

def formeln(c):
    Celsius = (Fahrenheit - 32.00) * 5.00/9.00
    return Celsius

def printC(answer):
    answer = str(roundTraditional(answer,2))
    print "\nYour Celsius value is " + answer + " C.\n"

main()

......应该能够给出您期望的结果。

您还可以使用decimal库来完成此操作,但是我建议的包装器更简单,某些情况下可能更可取。


编辑:感谢Blckknght指出5的边缘情况仅发生在某些值这里


这对负数不起作用,例如-4.625会评估为-4.62。你能修改它使其适用于负数吗? - JasonX

21

如果您需要在会计中四舍五入数字时避免浮点问题,可以使用numpy round。

您需要安装numpy:

pip install numpy

以及代码:

import numpy as np

print(round(2.675, 2))
print(float(np.round(2.675, 2)))

打印

2.67
2.68

如果你在合法的四舍五入情况下管理资金,那么你应该使用它。


如果最后一位数字是0,则此方法无效。例如,数字39.90将被舍入为39.9。 - martin36
1
此方法会返回一个十进制数值,而不是字符串。如果您想要指定格式的字符串,则应该使用 @jackz314。 - Samuel Dauzon
如果在树莓派上运行,请使用树莓派版本:apt install python3-numpy - Shawn
这个不起作用。 np.round(2.665, 2) 返回 2.66,而 round(2.665, 2) 返回 2.67。这是我的解决方案。https://dev59.com/HlwY5IYBdhLWcg3wF0he#53329223 - discover
@SamuelDauzon 当然了,我已经在本地尝试过了。我使用的是Python 3.7(win10)和Numpy 1.19.3,并且得到了我的结果。 - discover

13
float(str(round(answer, 2)))
float(str(round(0.0556781255, 2)))

11
如果您不仅需要舍入结果,而且还需要对舍入结果进行数学运算,则可以使用 decimal.Decimalhttps://docs.python.org/2/library/decimal.html
from decimal import Decimal, ROUND_DOWN

Decimal('7.325').quantize(Decimal('.01'), rounding=ROUND_DOWN)
Decimal('7.32') 

10
from decimal import Decimal, ROUND_HALF_UP

# Here are all your options for rounding:
# This one offers the most out of the box control
# ROUND_05UP       ROUND_DOWN       ROUND_HALF_DOWN  ROUND_HALF_UP
# ROUND_CEILING    ROUND_FLOOR      ROUND_HALF_EVEN  ROUND_UP

our_value = Decimal(16.0/7)
output = Decimal(our_value.quantize(Decimal('.01'), 
rounding=ROUND_HALF_UP))
print output

3
这应该是被采纳的答案。 - Zhang Buzz
1
“decimal”不是内置函数,因此它真的不应该成为被接受的答案。 - jwal
1
对于传统的四舍五入,这不应该是被接受的答案。 - Taras Mykhalchuk
此外,请始终显示输出... - not2qubit
@jwal 这是一个内置模块。 - bfontaine

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