Как округлить Double до ближайшего Int в swift?

Я пытаюсь сделать калькулятор с темпом роста (Double), который будет округлять результат до ближайшего целого и пересчитать оттуда как таковой:

let firstUsers = 10.0
let growth = 0.1
var users = firstUsers
var week = 0


while users < 14 {
    println("week \(week) has \(users) users")
    users += users * growth
    week += 1
}

но я пока не смог.

ИЗМЕНИТЬ Я вроде как сделал это так:

var firstUsers = 10.0
let growth = 0.1
var users:Int = Int(firstUsers)
var week = 0


while users <= 14 {
    println("week \(week) has \(users) users")
    firstUsers += firstUsers * growth
    users = Int(firstUsers)
    week += 1
}

Хотя я не возражаю, что он всегда округляется, мне это не нравится, потому что firstUsers должен был стать переменной и изменить всю программу (для того, чтобы сделать следующий расчет), что я не знаю, я хочу, чтобы это произошло.

Ответ 1

В библиотеке Foundation есть round (на самом деле это Darwin, но Foundation импортирует Darwin и большую часть времени вы захотите использовать Foundation вместо прямого Darwin).

import Foundation

users = round(users)

Запустите ваш код на игровой площадке, а затем позвоните:

print(round(users))

Выходы:

15,0

round() всегда округляется в большую сторону, если десятичный разряд равен >=.5 и в обратном направлении, когда он <.5 (стандартное округление). Вы можете использовать floor() для округления вверх и ceil() для округления вверх.

Если вам нужно округлить до определенного места, то умножьте на pow(10.0, number of places), round, а затем разделите на pow(10, number of places):

Округлить до 2 десятичных знаков:

let numberOfPlaces = 2.0
let multiplier = pow(10.0, numberOfPlaces)
let num = 10.12345
let rounded = round(num * multiplier) / multiplier
print(rounded)

Выходы:

10,12

Примечание: из-за того, как работает математика с плавающей запятой, rounded не всегда может быть совершенно точным. Лучше думать об этом как о приближении округления. Если вы делаете это для целей отображения, лучше использовать форматирование строки для форматирования числа, а не математические вычисления для его округления.

Ответ 2

Чтобы округлить двойное число до ближайшего целого, просто используйте round().

var x = 3.7
x.round() // x = 4.0

Если вы не хотите изменять исходное значение, используйте rounded():

let x = 3.7
let y = x.rounded() // y = 4.0. x = 3.7

Как и следовало ожидать (или нет), число вроде 3.5 округляется в -3.5 а число типа -3.5 округляется в -3.5 сторону. Если вам нужно другое поведение округления, чем это, вы можете использовать одно из правил округления. Например:

var x = 3.7
x.round(.towardZero) // 3.0

Если вам нужен фактический Int просто приведите его к одному (но только если вы уверены, что Double не будет больше Int.max):

let myInt = Int(myDouble.rounded())

Заметки

  • Этот ответ полностью переписан. Мой старый ответ имел дело с математическими функциями C, такими как round, lround, floor и ceil. Однако теперь, когда в Swift встроены эти функции, я больше не могу рекомендовать использовать эти функции. Спасибо @dfri за указание на это. Проверьте @dfri отличный ответ здесь. Я также сделал нечто подобное для округления CGFloat.

Ответ 3

Swift 3 и 4 - использование метода rounded(_:) как описано в протоколе FloatingPoint

Протокол FloatingPoint (которому соответствует, например, Double и Float) создает метод rounded(_:)

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

Эквивалент функции 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

Эквивалент функции round C.

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) // 4.0

.towardZero

Эквивалент функции 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 инициализации 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.

Из 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)
    }
}

Ответ 4

Swift 3: Если вы хотите округлить до определенного количества цифр, например. 5.678434 → 5.68 вы можете просто комбинировать функцию round() или roundf() с умножением:

    let value:Float = 5.678434
    let roundedValue = roundf(value * 100) / 100
    print(roundedValue) //5.68

Ответ 5

**In Swift**

var a = 14.123456789
var b = 14.123456789
var c = 14.123456789
var d = 14.123456789
var e = 14.123456789
var f = 14.123456789

a.rounded(.up)                      //15
b.rounded(.down)                    //14
c.rounded(.awayFromZero)            //15
d.rounded(.towardZero)              //14
e.rounded(.toNearestOrAwayFromZero) //14
f.rounded(.toNearestOrEven)         //14

Ответ 6

Вы также можете расширить FloatingPoint в Swift 3 следующим образом:

extension FloatingPoint {
    func rounded(to n: Int) -> Self {
        let n = Self(n)
        return (self / n).rounded() * n

    }
}

324.0.rounded(to: 5)   // 325

Ответ 7

Swift 3

var myNum = 8.09

myNum.rounded()//result = 8, который хранится в myNum