RoundedDecimal
RoundedDecimal 有两种口味;RoundedDecimal<T: DecimalPlaces>
和 DynamicRoundedDecimal
。不同的情况需要使用其中之一。
RoundedDecimal<T: DecimalPlaces>
Swift 小数,小数位数是类型的一部分。例如,RoundedDecimal<Places.five>
只能与其它 RoundedDecimal<Places.five>
值一起操作。这是在编译时保证的,但需要开发者事先知道需要哪种级别的精度。
示例
// listedPrice == 2.59
let listedPrice: RoundedDecimal<Places.two> = "2.5872659"
// exchangePrice == 1.12345
let exchangeRate: RoundedDecimal<Places.five> = "1.1234528492"
let localPrice = listedPrice * exchangeRate
将导致编译失败
binary operator '*' cannot be applied to operands of type 'RoundedDecimal<Places.two>' and 'RoundedDecimal<Places.five>'
let localPrice = listedPrice * exchangeRate
~~~~~~~~~~~~~~ ^ ~~~~~~~~~~~~
这些情况可以进行处理,但在乘法允许之前,开发者必须明确决定结果的精度。请参阅 RoundedDecimal
的文档获取更多信息。
DynamicRoundedDecimal
当所需的十进制位数在编译时无法确定时,此类类型非常有用。例如,处理在运行时决定且具有不同十进制位数的任意货币时。例如,美元有两位小数,但日元没有小数。在这种情况下,DynamicRoundedDecimal
非常合适,因为构造时提供了所需的十进制位数。
示例
// listedPrice == 2.59 after using a scale of 2 to represent USD
let listedPrice = DynamicRoundedDecimal(stringLiteral: "2.5872659", scale: 2)
// exchangePrice == 108.09364 after using a scale of 5
let exchangeRate = DynamicRoundedDecimal(stringLiteral: "108.0936412", scale: 5)
// localPrice = 279.96253 which uses the largest scale of either decimal, 5 in this case
let localPrice = listedPrice * exchangeRate
// appropriateLocalPrice = 280 after using a scale of 0 to represent JPY
let appropriateLocalPrice = localPrice.with(scale: 0)
安装
CocoaPods
pod 'RoundedDecimal', '~> 2.2.0'
Swift 包管理器
dependencies: [
.package(url: "https://github.com/SoftwareEngineerChris/RoundedDecimal.git", from: "2.2.0")
]
为什么
简略来说:我们希望保证小数精度,或者在更改精度时明确。
在处理小数时,我们经常想知道对我们的数值所代表的小数位数进行操作、处理或维护。
例如,在一个面向英国和美国的购物应用中处理货币时,我们希望处理具有两位小数的数字。特别是在处理大量的这些数字并将美元与英镑之间进行转换时。
如果我们有一个在美国售价为 $2.50 的产品,并且我们想在英国销售它,我们可能希望使用汇率来计算本地价格。如果我们的 API 提供的汇率是 0.81245 USD/GBP (或 1.23084 GBP/USD),通过简单的乘法,我们可以计算出产品的价格是 £3.0771。
我们可能不希望将£3.0771呈现给用户,因为他们通常不会以便士的分数进行交易。在我们的显示层中,我们可能在收据中将该值格式化为£3.08。用户已经决定订购300件这样的商品。我们的应用程序的计算部分不一定知道数据是如何呈现的,因此处理£3.0771的商品价格。因此,£3.0771乘以300等于£923.13。
在这种情况下,我们可能向用户展示如下收据:特殊商品 @ £3.08 x 300 = £923.13
但是300乘以£3.08并不等于£923.13。而是等于£924.00。用户对他们看到的总计感到困惑,没有意识到使用的计算价格是每件£3.0771,而不是显示的£3.08。
他们在收据上应该看到的是以下之一:特殊商品 @ £3.08 x 300 = £924.00
或特殊商品 @ £3.0771 x 300 = £923.13
如何处理这一问题应该是一个业务决策,但我们应该能够保证代码中该决策的结果。如果使用的货币或至少所需的十进制长度在编译时是静态且已知的,我们可以使用RoundedDecimal
来将其作为一个编译时的要求。或者,如果我们在运行时处理货币或十进制长度,我们可以使用DynamicRoundedDecimal
来处理这种情况。查看每种类型的文档以了解如何进行这种处理。