Swift 3 和 4 - 使用 rounded(_:) 方法,如 FloatingPoint 协议中的蓝图
FloatingPoint protocol(例如Double 和Float 符合)蓝图rounded(_:) method
func rounded(_ rule: FloatingPointRoundingRule) -> Self
其中FloatingPointRoundingRule 是枚举多个不同舍入规则的枚举:
case awayFromZero
四舍五入到最接近的允许值,其幅度大于或
与源的相同。
case down
四舍五入到小于或等于的最接近的允许值
来源。
case toNearestOrAwayFromZero
四舍五入到最接近的允许值;如果两个值同样接近,
选择幅度更大的那个。
case toNearestOrEven
四舍五入到最接近的允许值;如果两个值同样接近,
偶数被选中。
case towardZero
四舍五入到最接近的允许值,其幅度小于或
与源的相同。
case up
四舍五入到大于或等于的最接近的允许值
来源。
我们使用与@Suragch's excellent answer 中的示例类似的示例来在实践中展示这些不同的舍入选项。
.awayFromZero
四舍五入到最接近的允许值,其幅度大于或等于源的幅度; C 函数之间没有直接等效项,因为它使用 self、ceil 或 floor 的符号,分别对应 self 的正值和负值。
3.000.rounded(.awayFromZero) // 3.0
3.001.rounded(.awayFromZero) // 4.0
3.999.rounded(.awayFromZero) // 4.0
(-3.000).rounded(.awayFromZero) // -3.0
(-3.001).rounded(.awayFromZero) // -4.0
(-3.999).rounded(.awayFromZero) // -4.0
.down
等效于 C 中的floor 函数。
3.000.rounded(.down) // 3.0
3.001.rounded(.down) // 3.0
3.999.rounded(.down) // 3.0
(-3.000).rounded(.down) // -3.0
(-3.001).rounded(.down) // -4.0
(-3.999).rounded(.down) // -4.0
.toNearestOrAwayFromZero
等效于 C 中的round 函数。
3.000.rounded(.toNearestOrAwayFromZero) // 3.0
3.001.rounded(.toNearestOrAwayFromZero) // 3.0
3.499.rounded(.toNearestOrAwayFromZero) // 3.0
3.500.rounded(.toNearestOrAwayFromZero) // 4.0
3.999.rounded(.toNearestOrAwayFromZero) // 4.0
(-3.000).rounded(.toNearestOrAwayFromZero) // -3.0
(-3.001).rounded(.toNearestOrAwayFromZero) // -3.0
(-3.499).rounded(.toNearestOrAwayFromZero) // -3.0
(-3.500).rounded(.toNearestOrAwayFromZero) // -4.0
(-3.999).rounded(.toNearestOrAwayFromZero) // -4.0
也可以使用零参数rounded() method 访问此舍入规则。
3.000.rounded() // 3.0
// ...
(-3.000).rounded() // -3.0
// ...
.toNearestOrEven
四舍五入到最接近的允许值;如果两个值同样接近,则选择偶数;相当于 C 的rint(/非常类似于nearbyint)函数。
3.499.rounded(.toNearestOrEven) // 3.0
3.500.rounded(.toNearestOrEven) // 4.0 (up to even)
3.501.rounded(.toNearestOrEven) // 4.0
4.499.rounded(.toNearestOrEven) // 4.0
4.500.rounded(.toNearestOrEven) // 4.0 (down to even)
4.501.rounded(.toNearestOrEven) // 5.0 (up to nearest)
.towardZero
等效于 C 中的trunc 函数。
3.000.rounded(.towardZero) // 3.0
3.001.rounded(.towardZero) // 3.0
3.999.rounded(.towardZero) // 3.0
(-3.000).rounded(.towardZero) // 3.0
(-3.001).rounded(.towardZero) // 3.0
(-3.999).rounded(.towardZero) // 3.0
如果舍入的目的是准备使用整数(例如,在舍入后使用Int by FloatPoint 初始化),我们可以简单地利用这样一个事实,即在初始化Int 时使用@ 987654366@(或Float等),小数部分会被截掉。
Int(3.000) // 3
Int(3.001) // 3
Int(3.999) // 3
Int(-3.000) // -3
Int(-3.001) // -3
Int(-3.999) // -3
.up
等效于 C 中的ceil 函数。
3.000.rounded(.up) // 3.0
3.001.rounded(.up) // 4.0
3.999.rounded(.up) // 4.0
(-3.000).rounded(.up) // 3.0
(-3.001).rounded(.up) // 3.0
(-3.999).rounded(.up) // 3.0
附录:访问 FloatingPoint 的源代码以验证 C 函数与不同 FloatingPointRoundingRule 规则的等效性
如果我们愿意,我们可以查看FloatingPoint 协议的源代码,以直接查看与公共FloatingPointRoundingRule 规则等效的C 函数。
从swift/stdlib/public/core/FloatingPoint.swift.gyb 我们看到rounded(_:) 方法的默认实现使我们使用了变异的round(_:) 方法:
public func rounded(_ rule: FloatingPointRoundingRule) -> Self {
var lhs = self
lhs.round(rule)
return lhs
}
从swift/stdlib/public/core/FloatingPointTypes.swift.gyb 我们发现round(_:) 的默认实现,其中FloatingPointRoundingRule 规则和C 舍入函数之间的等价性显而易见:
public mutating func round(_ rule: FloatingPointRoundingRule) {
switch rule {
case .toNearestOrAwayFromZero:
_value = Builtin.int_round_FPIEEE${bits}(_value)
case .toNearestOrEven:
_value = Builtin.int_rint_FPIEEE${bits}(_value)
case .towardZero:
_value = Builtin.int_trunc_FPIEEE${bits}(_value)
case .awayFromZero:
if sign == .minus {
_value = Builtin.int_floor_FPIEEE${bits}(_value)
}
else {
_value = Builtin.int_ceil_FPIEEE${bits}(_value)
}
case .up:
_value = Builtin.int_ceil_FPIEEE${bits}(_value)
case .down:
_value = Builtin.int_floor_FPIEEE${bits}(_value)
}
}