如何在Double中将Double舍入到最近的Int?

dua*_*ris 148 double int rounding 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
}
Run Code Online (Sandbox Code Playgroud)

但到目前为止我一直无法做到.

编辑 我有点喜欢这样:

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
}
Run Code Online (Sandbox Code Playgroud)

虽然我不介意它总是四舍五入,但我不喜欢它,因为firstUsers必须成为变量并在整个程序中进行更改(为了进行下一次计算),我不希望它发生.

Mik*_*e S 224

库中有一个round可用的(它实际上是,但是进口和大部分时间你都想使用而不是直接使用).FoundationDarwinFoundationDarwinFoundationDarwin

import Foundation

users = round(users)
Run Code Online (Sandbox Code Playgroud)

在游乐场中运行代码然后调用:

print(round(users))
Run Code Online (Sandbox Code Playgroud)

输出:

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)
Run Code Online (Sandbox Code Playgroud)

输出:

10.12

注意:由于浮点数学的工作方式,rounded可能并不总是完全准确.最好把它想象成舍入的近似值.如果您是出于显示目的而这样做,最好使用字符串格式来格式化数字,而不是使用数学来舍入它.

  • 还有`lround()`返回一个`Int`. (46认同)
  • @丹尼尔T。- 不是错误。它向上舍入到最接近的较大负数。这样想,+16.5 到 +17 距离零又多了 0.5。这意味着 -16.5 到 -17 也距离零远 0.5。Ceil 则相反,+16.5 到 +16 是更接近零的 0.5,-16.5 到 -16 也是更接近零的 0.5 (2认同)

Sur*_*gch 131

要将double舍入到最接近的整数,只需使用round().

var x = 3.7
x.round() // x = 4.0
Run Code Online (Sandbox Code Playgroud)

如果您不想修改原始值,请使用rounded():

let x = 3.7
let y = x.rounded() // y = 4.0. x = 3.7
Run Code Online (Sandbox Code Playgroud)

正如人们可能期望的那样(或者可能没有),数字之类的数字3.5被四舍五入,数字之类的数字-3.5被向下舍入.如果您需要不同的舍入行为,则可以使用其中一个舍入规则.例如:

var x = 3.7
x.round(.towardZero) // 3.0
Run Code Online (Sandbox Code Playgroud)

如果你需要一个实际的,Int那么只需将它投射到一个(但只有当你确定Double不会大于Int.max)时:

let myInt = Int(myDouble.rounded())
Run Code Online (Sandbox Code Playgroud)

笔记

  • 这个答案完全被重写了.我的老回答处理像C数学函数round,lround,floor,和ceil.但是,现在Swift内置了这个功能,我不能再推荐使用这些功能了.感谢@dfri向我指出这一点.在这里查看@ dfri的优秀答案.我也做了类似的东西舍入CGFloat.


dfr*_*fri 67

Swift 3和4 - rounded(_:)FloatingPoint协议中使用该方法作为蓝图

FloatingPoint协议(例如DoubleFloat符合协议)为该方法设计蓝图rounded(_:)

func rounded(_ rule: FloatingPointRoundingRule) -> Self
Run Code Online (Sandbox Code Playgroud)

哪里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
Run Code Online (Sandbox Code Playgroud)

.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
Run Code Online (Sandbox Code Playgroud)

.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
Run Code Online (Sandbox Code Playgroud)

也可以使用零参数rounded()方法访问此舍入规则.

3.000.rounded() // 3.0
// ...

(-3.000).rounded() // -3.0
// ...
Run Code Online (Sandbox Code Playgroud)

.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
Run Code Online (Sandbox Code Playgroud)

.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
Run Code Online (Sandbox Code Playgroud)

如果舍入的目的是准备使用整数(例如Int,FloatPoint在舍入后使用初始化),我们可能只是使用这样的事实:当初始化Int使用a 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
Run Code Online (Sandbox Code Playgroud)

.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
Run Code Online (Sandbox Code Playgroud)

附录:访问源代码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
}
Run Code Online (Sandbox Code Playgroud)

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)
    }
}
Run Code Online (Sandbox Code Playgroud)


Leo*_*bus 6

您还可以在 Swift 3 中扩展 FloatingPoint,如下所示:

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

    }
}

324.0.rounded(to: 5)   // 325
Run Code Online (Sandbox Code Playgroud)


Tho*_*oms 6

Swift 3:如果要舍入到某个数字,例如5.678434-> 5.68,可以将round()或roundf()函数与一个乘法结合起来:

    let value:Float = 5.678434
    let roundedValue = roundf(value * 100) / 100
    print(roundedValue) //5.68
Run Code Online (Sandbox Code Playgroud)


Sai*_*ddy 6

**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
Run Code Online (Sandbox Code Playgroud)