Swift 3 и 4 - использование метода rounded(_:)
, как это предусмотрено в протоколе FloatingPoint
_ 6_ метод
func rounded(_ rule: FloatingPointRoundingRule) -> Self
Где FloatingPointRoundingRule
- это перечисление, в котором перечисляются различные правила округления:
case awayFromZero
Округлить до ближайшего допустимого значения, величина которого больше или равна значению источника.
case down
Округлите до ближайшего допустимого значения, которое меньше или равно источнику.
case toNearestOrAwayFromZero
Округлить до ближайшего допустимого значения; если два значения одинаково близки, выбирается одно с большей величиной.
case toNearestOrEven
Округлить до ближайшего допустимого значения; если два значения одинаково близки, выбирается четное.
case towardZero
Округлите до ближайшего допустимого значения, величина которого меньше или равна значению источника.
case up
Округлите до ближайшего допустимого значения, которое больше или равно источнику.
Мы используем примеры, аналогичные приведенным в отличном ответе @Suragch, чтобы продемонстрировать эти различные варианты округления на практике.
.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()
метода с нулевым аргументом.
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
путем FloatPoint
инициализации после округления), мы могли бы просто использовать тот факт, что при инициализации Int
с использованием Double
(или 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
, чтобы напрямую увидеть эквиваленты функций C общедоступным FloatingPointRoundingRule
правилам.
Из public / stdd. FloatingPoint.swift.gyb мы видим, что реализация метода rounded(_:)
по умолчанию делает нас мутирующим методом round(_:)
:
public func rounded(_ rule: FloatingPointRoundingRule) -> Self {
var lhs = self
lhs.round(rule)
return lhs
}
Из swift 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)
}
}
person
dfrib
schedule
05.01.2017