分项计算的舍入规则
Rounding rules for itemized calculations
在浏览了几个 Whosebug 帖子和许多网站之后,我直接向这里的聪明人询问了这个问题。我们的平台处理税收、折扣等的货币计算。我们目前只关注美元和加元。我们是一家非常标准的商店,运行 我们在 python 上提供后端服务,在前端,我们在 iOS 和 Andriod 上有一些应用程序。
我们在后端进行所有计算,我们使用 python 的 decimal
进行所有计算,并在 UI 中显示值或实际处理之前进行量化付款。我们的初始定价通常以美分和整数表示,但最终可能会以最多小数点后 4 位的值表示。这就是它变得有趣的地方。
这是一个基本示例:
*** These values are calculated in the backed ***
[1a] Price of item (in dollars): .75
[1b] Price of item (in cents): 375
[1c] Tax rate: 6.25%
[1d] Calculated tax (in cents): 23.4375 ( = 375 * 6.25%)
[1e] Tip: 15%
[1f] Calculated tip (in cents): 56.2500 ( = 375 * 15%)
[1g] Total (in cents): 454.6875 ( = 375 + 23.4375 + 56.2500)
[1h] Total (in dollars and rounded): .55
*** This is visible to user ***
[2a] Price of item (in dollars): .75
// Value for [2b] is taken and rounded from value of [1d]
[2b] Tax (in dollars and rounded): [=10=].23
// Value for [2c] is taken and rounded from value of [1f]
[2c] Tip (in dollars and rounded): [=10=].56
// Value for [2d] is taken and rounded from value of [1g]
[2d] Total (in dollars and rounded): .55
However, if you add [2a], [2b] and [2c], you get:
[2e] 3.75 + 0.23 + 0.56 = 4.54
如您所见,[2e] 和 [1h] 相差一分钱。
计算和显示货币金额的最佳方式是什么。
一般来说,如果你想在后端求和然后舍入,你想要显示舍入的行项目,并且你希望舍入的行项目加起来等于相同的总数,那么至少有一个行项目可能不得不四舍五入不正确最多一分钱。您唯一的选择是至少打破其中一个要求。一些可能的方法(您应该 运行 由熟悉您 jurisdiction/business 的律师进行)包括:
- 调整后端代码。如果 15% 的小费即使作为订单项也没有四舍五入到最接近的美分,我个人会觉得有点奇怪。
- 不显示某些行项目(或者,例如,将 Tax 和 Tip 分组到一行中,以便在分组时 sum-then-round 和 round-then-sum 策略匹配)
- 只需使用前端总计而不是后端总计,将 <=$0.005 的损失作为一项业务来避免客户服务问题。
- 向最终用户显示更高的精度。
- 包括一个 footnote/FAQ 以教育用户潜在的差异。
- 正在调整一些订单项以包括缺失的便士。
在浏览了几个 Whosebug 帖子和许多网站之后,我直接向这里的聪明人询问了这个问题。我们的平台处理税收、折扣等的货币计算。我们目前只关注美元和加元。我们是一家非常标准的商店,运行 我们在 python 上提供后端服务,在前端,我们在 iOS 和 Andriod 上有一些应用程序。
我们在后端进行所有计算,我们使用 python 的 decimal
进行所有计算,并在 UI 中显示值或实际处理之前进行量化付款。我们的初始定价通常以美分和整数表示,但最终可能会以最多小数点后 4 位的值表示。这就是它变得有趣的地方。
这是一个基本示例:
*** These values are calculated in the backed ***
[1a] Price of item (in dollars): .75
[1b] Price of item (in cents): 375
[1c] Tax rate: 6.25%
[1d] Calculated tax (in cents): 23.4375 ( = 375 * 6.25%)
[1e] Tip: 15%
[1f] Calculated tip (in cents): 56.2500 ( = 375 * 15%)
[1g] Total (in cents): 454.6875 ( = 375 + 23.4375 + 56.2500)
[1h] Total (in dollars and rounded): .55
*** This is visible to user ***
[2a] Price of item (in dollars): .75
// Value for [2b] is taken and rounded from value of [1d]
[2b] Tax (in dollars and rounded): [=10=].23
// Value for [2c] is taken and rounded from value of [1f]
[2c] Tip (in dollars and rounded): [=10=].56
// Value for [2d] is taken and rounded from value of [1g]
[2d] Total (in dollars and rounded): .55
However, if you add [2a], [2b] and [2c], you get:
[2e] 3.75 + 0.23 + 0.56 = 4.54
如您所见,[2e] 和 [1h] 相差一分钱。 计算和显示货币金额的最佳方式是什么。
一般来说,如果你想在后端求和然后舍入,你想要显示舍入的行项目,并且你希望舍入的行项目加起来等于相同的总数,那么至少有一个行项目可能不得不四舍五入不正确最多一分钱。您唯一的选择是至少打破其中一个要求。一些可能的方法(您应该 运行 由熟悉您 jurisdiction/business 的律师进行)包括:
- 调整后端代码。如果 15% 的小费即使作为订单项也没有四舍五入到最接近的美分,我个人会觉得有点奇怪。
- 不显示某些行项目(或者,例如,将 Tax 和 Tip 分组到一行中,以便在分组时 sum-then-round 和 round-then-sum 策略匹配)
- 只需使用前端总计而不是后端总计,将 <=$0.005 的损失作为一项业务来避免客户服务问题。
- 向最终用户显示更高的精度。
- 包括一个 footnote/FAQ 以教育用户潜在的差异。
- 正在调整一些订单项以包括缺失的便士。