【问题标题】:Calculate a tip & total, without rounding errors. (Python)计算小费和总数,没有四舍五入误差。 (Python)
【发布时间】:2013-09-11 20:29:46
【问题描述】:

这不是格式问题。

我正在做一些学习/exrcize,并决定在 Python 中创建一个“小费计算器”。我很清楚某些数字、使用浮点数等可能存在舍入错误。而且我知道我应该尽可能只处理便士/整数。

在根据百分比计算总计(以美元为单位)时,如何正确避免四舍五入?

理想情况下,我应该有一个函数,它接受 percentagesubtotal 并返回“小费”总数(基于百分比)和新票总数 -- 在不四舍五入的情况下进行货币计算,就像我在纸上做的一样 / 在我的计算器上。

目前,我有这样的事情:

import decimal

def get_tip(percentage, pennies_sub_total):
    """"
    param percentage: I suspect this should be int() or decimal.Decimal. I'm not aware of a condition that would make it matter either way. You? 
    param pennies_sub_total = int()
    """
    percentage = decimal.Decimal(percentage)
    pennies_sub_total = decimal.Decimal(pennies_sub_total)  # Unnecessary use of Decimal?
    tip = (pennies_sub_total * percentage) / 100
    total = (pennies_sub_total + tip)
    return {'tip': tip, 'total': total} 

...这似乎可行,但我不确定如何严格测试它——所以我来这里进行代码审查。 我是否忽略了任何明显的东西?我是否以我应该有信心的方式做到这一点?

更新

鉴于其中一个答案 (https://stackoverflow.com/a/18751401/26196) 中提出的问题,如果有帮助,我将尝试解决这些问题:

  1. 百分比的类型是什么?
  2. pennies_sub_total 的类型是什么? (编辑 - 你确实提到这是 int)
  3. 分配后的百分比是否与传入时的类型相同。
  4. 您是否计划将它们作为 Decimal、int、float、str 处理?
  5. 然后你有问题要回答,小费的类型和总数。 “公式”中的 100 将是一个整数。小费的类型是什么?
  6. 正如所指出的,您还必须确定 1.8855 是否是您想要的 12.57 的 15% 的结果。
  1. intdecimal.Decimal。我不确定这两者之间是否重要......?
  2. int,但这个问题已经解决了。
  3. 也许?它没有被退回。如果我搞砸了一些范围的东西,请告诉我。这并不是要修改此函数“范围”之外的任何变量。
  4. 见 1 和 2。
  5. tip 应该以decimal.Decimal 或整数“便士”的形式返回。在现有的代码示例中,我相信我模棱两可地将其保留为浮点数。这个特定的行/作业是提供答案的特定位置,因为它是完成“真正”工作的地方。
  6. 认为我的问题很清楚地表明,任何小于一分钱的东西都应该被忽略。 “1.8855”是一个很好的结果,只要任何数学处理“小计+小费”部分不会向上/向下舍入,而是简单地将便士加起来——再次,另一个提供建议的好地方,因为这就是我想要的以确保我做得正确。

【问题讨论】:

  • “没有四舍五入,就像...在纸上”没有意义。 1 美分餐的 15% 小费是多少?
  • “所以我来这里进行代码审查” --> 试试codereview
  • @Teepeemm 我忘了我在和程序员打交道:“0”是你问题的答案。
  • @askewchan 没有意识到那是一回事。感谢您的提示!
  • @BurhanKhalid 也许我在以前的编辑中更正了我的代码,但我没有看到那行。

标签: python math currency


【解决方案1】:
>>> import decimal

>>> decimal.Decimal('1.99')
Decimal('1.99')

这个模块的目的是支持使用熟悉的算术 “校舍”规则并避免一些棘手的表示 与二进制浮点相关的问题。包裹特别 对金融应用程序或用户有 与二进制浮点不一致的期望(例如, 在二进制浮点中, 1.00 % 0.1 给出 0.09999999999999995 十进制浮点返回的预期 Decimal('0.00'))。

【讨论】:

  • 为什么您的答案中的文字会突出显示?如果这是引用,您能引用出处吗?谢谢。
  • 在十进制模块的文档中;帮助(十进制)会做:-)
  • 我确定您是对的,但我在最新版本的文档中没有看到该引用:docs.python.org/2/library/decimal.html#module-decimal(当前)。
  • 另外,由于我已经在使用十进制模块,并且查看了文档(在我的问题中明确显示)我不确定控制台代码应该如何成为“答案” .我正处于知道“我在做什么”的阶段,但我想正在寻找“我做对了”的输入/确认。
  • 这根本不能真正回答最初的问题......我承认这不是很好的范围。
【解决方案2】:

您有很多问题,并留下一些问题让我们猜测。

  1. 百分比的类型是什么?
  2. pennies_sub_total 的类型是什么(编辑 - 你确实提到这是 int)
  3. 分配后的百分比是否与传入时的类型相同。
  4. 您是否计划将它们作为 Decimal、int、float、str 处理?
  5. 然后你有问题要回答,小费的类型和总数。 “公式”中的 100 将是一个整数。小费的类型是什么?
  6. 正如所指出的,您还必须确定 1.8855 是否是您想要的 12.57 的 15% 的结果。

要回答这些问题,我建议您只需了解一下函数是什么并显示在 python 解释器中运行的结果。例如,

>>> tip = (pennies_sub_total * percentage) / 100
>>> tip

【讨论】:

  • 正如我希望在问题中表达的那样,我对现有的解决方案没有完全的信心——因此,我给出了(我认为是的)一个体面的“例子”,故意有点模棱两可,以便为更正的解决方案留出空间。我将尝试解决您指出的问题,并从那里了解情况如何。
  • 好问题。我试图在编辑中专门解决它们。
【解决方案3】:

算术的精度不是问题:如果结果相差 10-14 美分,那就足够接近了。真正的问题是对结果进行四舍五入,这样您就不会显示比有效数字更多的数字。这是一个很容易解决的问题:

>>> print "tip: %.2f total: %.2f" % (0.15*12.57, 1.15*12.57)
tip: 1.89 total: 14.46

【讨论】:

  • 当我使用计算器并执行“12.57 * 0.15”时,我得到“1.8855” - 正如预期的那样。因此,我会在“12.57”中加上“1.88”,得到“14.45”的总和——我是不是做错了餐桌数学,把餐馆搞砸了?
猜你喜欢
  • 1970-01-01
  • 2022-01-09
  • 1970-01-01
  • 2014-10-29
  • 2016-09-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多