在Python中将答案四舍五入到2位小数

12

我遇到的问题是将我的结果四舍五入保留两位小数。虽然我的应用程序获得了正确的结果,但我很难像货币一样将其四舍五入至最近的小数。

cost = input("\nEnter the 12 month cost of the Order: ")
cost = float(cost)

print("\n12 Month Cost:",
  cost * 1,"USD")
print("6 Month Cost:",
  cost * 0.60,"USD")
print("3 Month Cost:",
  cost * 0.36,"USD")

例如,如果12个月的价格为23美元,6个月的价格为13.799999999999999美元,但我希望显示13.80。

我在谷歌上搜索了如何舍入数字,但找不到太多关于舍入结果的帮助。


1
关于你的12个月、6个月和3个月成本的乘数,我要提一个观点...我认为这些应该是1、0.5和0.25,而不是1、0.6和0.36。你现在计算的是12个月的50%(6个月)和25%(3个月)。 - dhj
@dhj 可能是在编写一个订阅系统,根据订阅时间长度提供最佳折扣。订阅六个月只需13.80美元,但订阅十二个月比一年的费用便宜4.60美元! - kreativitea
@kreativitea ... 很好的观点!我做很多数学/科学数据处理。这是我的一个尴尬的假设。 - dhj
不用担心,dhj,我也有同样的想法,直到我看到你已经写了它...只有在你发表评论之后,我才想到这个例外;我相信如果我们以不同的顺序到达,我们的立场可能会颠倒。 - kreativitea
5个回答

15

您应该使用格式说明符:

print("6 Month Cost: %.2fUSD" % (cost * .6))

更好的做法是完全不依赖于浮点数,而是使用decimal模块,它提供了任意精度和更多关于舍入方法的控制:

from decimal import Decimal, ROUND_HALF_UP
def round_decimal(x):
  return x.quantize(Decimal(".01"), rounding=ROUND_HALF_UP)

cost = Decimal(input("Enter 12 month cost: "))
print("6 Month Cost: ", round_decimal(cost * Decimal(".6")))

除了货币格式之外,如果我们在常规的Python十进制数上使用格式说明符而不是使用decimal模块,通常会有更好的性能表现,您认为呢? - jvriesem

3

一种经典的方法是将数值乘以100,加上0.5(这是为了四舍五入),然后使用int()函数将结果转换为整数。现在你得到了四舍五入后的分数,再将其除以100,即可得到四舍五入后的浮点数。

cost = 5.5566
cost *= 100 # cost = 555.66
cost += 0.5 # cost = 556.16
cost = int(cost) # cost = 556
cost /= float(100) # cost =  5.56

cost = 5.4444
cost = int(( cost * 100 ) + 0.5) / float(100) # cost = 5.44

为什么人们更喜欢十进制而不是这种方法? - Serhii Kushchenko
为什么人们更喜欢十进制而不是这种方法? - undefined

2
如果您只想将其作为字符串处理,可以使用格式化函数:
format(cost, '.2f')

该函数返回一个字符串,其格式与第二个参数中定义的格式相同。因此,如果 cost 包含 3.1418,则上面的代码将返回字符串 '3.14'。

1

如果您只是想打印它,字符串格式化就可以解决:

print("\n12 Month Cost:%.2f USD"%(cost*1))

0
在一些国家,只允许使用5的倍数来表示分。所以,f{money:.2f'}只是截取了多余的数字,但还需要进一步进行四舍五入,使其成为最接近的5的倍数。
例如,1.233333将被格式化为1.23,然后四舍五入到最接近的5的倍数,即1.25。或者,1.27将变为1.25
这里是我基于字符串操作的解决方案。
def cround(x:float) -> float:
    """Currency rounder"""
    # round to 2 decimal places
    s = f"{x:.2f}"
    # round to 5 or 0 cent
    i, dot, d = s.partition('.')
    d1, d2 = d
    # check last digit
    if d2 in "05": #    stay the same
        return float(s)
    elif d2 in "12": #  round down
        d = d1 + "0"
    elif d2 in "67": #  round down
        d = d1 + "5"
    elif d2 in "34": #  round up
        d = d1 + "5"
    elif d2 in "89": #  round up
        d2 = "0"
        if int(d1) + 1 < 9:
            d = str(int(d1) + 1) + '0'
        else:
            d = '00'
            i = str(int(i) + 1)      
      
    return float(''.join([i, dot, d]))


# test
ms     = [1.62, 1.63, 1.67, 1.68, 2.1, 2.111, 2.119, 2.138]
ms_res = [1.60, 1.65, 1.65, 1.70, 2.1, 2.100, 2.100, 2.150] # expected rounded values

# result
for m, m_true in zip(ms, ms_res):
    print(m, cround(m), cround(m) == m_true)

输出

1.62 1.6 True
1.63 1.65 True
1.67 1.65 True
1.68 1.7 True
2.1 2.1 True
2.111 2.1 True
2.119 2.1 True
2.138 2.15 True

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