在swift中将double值舍入为x个小数位数

Lei*_*ton 359 double nstimeinterval ios swift

谁能告诉我如何在Swift中将double值舍入到x个小数位?

我有:

var totalWorkTimeInHours = (totalWorkTime/60/60)
Run Code Online (Sandbox Code Playgroud)

totalWorkTime在第二个是NSTimeInterval(双).

totalWorkTimeInHours 会给我时间,但它给了我这么长的精确数字的时间,例如1.543240952039 ......

当我打印时,如何将其舍入到1.543 totalWorkTimeInHours

Seb*_*ian 408

Swift 2的扩展

更通用的解决方案是以下扩展,适用于Swift 2和iOS 9:

extension Double {
    /// Rounds the double to decimal places value
    func roundToPlaces(places:Int) -> Double {
        let divisor = pow(10.0, Double(places))
        return round(self * divisor) / divisor
    }
}
Run Code Online (Sandbox Code Playgroud)


Swift 3的扩展

在Swift 3中round被替换为rounded:

extension Double {
    /// Rounds the double to decimal places value
    func rounded(toPlaces places:Int) -> Double {
        let divisor = pow(10.0, Double(places))
        return (self * divisor).rounded() / divisor
    }
}
Run Code Online (Sandbox Code Playgroud)


返回Double舍入到4位小数的示例:

let x = Double(0.123456789).roundToPlaces(4)  // x becomes 0.1235 under Swift 2
let x = Double(0.123456789).rounded(toPlaces: 4)  // Swift 3 version
Run Code Online (Sandbox Code Playgroud)

  • Swift's Double的本质似乎是它不精确 - 因为它以二进制形式存储/访问,即使使用这种舍入函数也不会返回舍入到3位小数的数字:例如,`round(8.46*pow( 10.0,3.0))/ pow(10.0,3.0)`返回`8.460000000000001`.事实上,在这种情况下,至少在这种情况下做同样的事情似乎也有效:`round(Float(8.46)*pow(10.0,3.0))/ pow(10.0,3.0)`产生`8.46`.只是值得注意的事情. (15认同)
  • 不幸的是,这在Swift 3中不再起作用,我收到此错误信息'没有'*'候选者产生预期的上下文结果类型'FloatingPointRoundingRule'` (2认同)
  • 我更新了解决方案并添加了Swift 3的扩展. (2认同)
  • 要更加迅速3 ...你应该改变func四舍五入(toPlaces places:Int) - > Double (2认同)
  • @BenSaufley但是如果输入98.68它也不起作用.在这种情况下,我得到98.6800003 (2认同)
  • 我喜欢更通用的浮点数扩展: `extension FloatingPoint { func roundTo(places:Int) -> Self { let divisor = Self(Int(pow(10.0, Double(places)))) return (self * divisor).rounded () / 除数 } }` (2认同)

zis*_*oft 364

您可以使用Swift的round功能来完成此任务.

Double以3位数精度舍入a ,首先将其乘以1000,将其四舍五入并将舍入结果除以1000:

let x = 1.23556789
let y = Double(round(1000*x)/1000)
print(y)  // 1.236
Run Code Online (Sandbox Code Playgroud)

除了任何类型printf(...)String(format: ...)解决方案之外,此操作的结果仍然是类型Double.

编辑:
关于它有时不起作用的评论,请阅读:

每个计算机科学家应该知道的浮点运算

  • 在操场上对我不起作用:```let rate = 9.94999999999; 双(圆(速率*100)/ 100);```输出:````9.94999999999,9.949999999999999```仅适用于打印,但如何将其分配给变量? (27认同)
  • "每个计算机科学家应该知道的关于浮点运算的内容"是73页长.什么是TL; DR在那?:) (11认同)
  • @HardikDG 我不记得了,抱歉 :-) (2认同)

vac*_*ama 303

使用totalWorkTimeInHourstotalWorkTimeInHours字符串的构造函数:

print(String(format: "%.3f", totalWorkTimeInHours))
Run Code Online (Sandbox Code Playgroud)

  • @Eyeball:实际上,它是圆的.它与C printf功能的行为相同,后者会舍入到请求的数字.所以`String(格式:"%.3f",1.23489)`打印`1.235` (28认同)
  • 这是截断,而不是四舍五入 (23认同)
  • @ pr1001,也许是这样,但当时并不清楚,其他46人发现我的答案很有用.Stack Overflow不仅仅是帮助OP. (14认同)
  • 原始海报正在寻找要使用的数值,而不是要显示的字符串. (6认同)
  • 奇怪,每次都返回0.00. (3认同)
  • @pr1001 OP 特别询问:“当我*打印*totalWorkTimeInHours 时,如何将其舍入为 1.543?” 因此,OP 正在讨论如何显示数字,因此“String”解决方案是完全合法的。 (2认同)

Ima*_*tit 227

使用Swift 4.2,根据您的需要,您可以选择以下9种样式中的一种,以获得a的舍入结果Double.


#1.使用FloatingPoint rounded()方法

在最简单的情况下,您可以使用该Double round()方法.

let roundedValue1 = (0.6844 * 1000).rounded() / 1000
let roundedValue2 = (0.6849 * 1000).rounded() / 1000
print(roundedValue1) // returns 0.684
print(roundedValue2) // returns 0.685
Run Code Online (Sandbox Code Playgroud)

#2.使用FloatingPoint rounded(_:)方法

let roundedValue1 = (0.6844 * 1000).rounded(.toNearestOrEven) / 1000
let roundedValue2 = (0.6849 * 1000).rounded(.toNearestOrEven) / 1000
print(roundedValue1) // returns 0.684
print(roundedValue2) // returns 0.685
Run Code Online (Sandbox Code Playgroud)

#3.使用达尔文round功能

基金会round通过达尔文提供功能.

import Foundation

let roundedValue1 = round(0.6844 * 1000) / 1000
let roundedValue2 = round(0.6849 * 1000) / 1000
print(roundedValue1) // returns 0.684
print(roundedValue2) // returns 0.685
Run Code Online (Sandbox Code Playgroud)

#4.使用使用DoubleDarwin roundpow函数构建的扩展自定义方法

如果您想多次重复上一个操作,重构代码可能是个好主意.

import Foundation

extension Double {
    func roundToDecimal(_ fractionDigits: Int) -> Double {
        let multiplier = pow(10, Double(fractionDigits))
        return Darwin.round(self * multiplier) / multiplier
    }
}

let roundedValue1 = 0.6844.roundToDecimal(3)
let roundedValue2 = 0.6849.roundToDecimal(3)
print(roundedValue1) // returns 0.684
print(roundedValue2) // returns 0.685
Run Code Online (Sandbox Code Playgroud)

#5.使用NSDecimalNumber rounding(accordingToBehavior:)方法

如果需要,NSDecimalNumber为舍入十进制数提供一个冗长但功能强大的解决方案.

import Foundation

let scale: Int16 = 3

let behavior = NSDecimalNumberHandler(roundingMode: .plain, scale: scale, raiseOnExactness: false, raiseOnOverflow: false, raiseOnUnderflow: false, raiseOnDivideByZero: true)

let roundedValue1 = NSDecimalNumber(value: 0.6844).rounding(accordingToBehavior: behavior)
let roundedValue2 = NSDecimalNumber(value: 0.6849).rounding(accordingToBehavior: behavior)

print(roundedValue1) // returns 0.684
print(roundedValue2) // returns 0.685
Run Code Online (Sandbox Code Playgroud)

#6.使用NSDecimalRound(_:_:_:_:)功能

import Foundation

let scale = 3

var value1 = Decimal(0.6844)
var value2 = Decimal(0.6849)

var roundedValue1 = Decimal()
var roundedValue2 = Decimal()

NSDecimalRound(&roundedValue1, &value1, scale, NSDecimalNumber.RoundingMode.plain)
NSDecimalRound(&roundedValue2, &value2, scale, NSDecimalNumber.RoundingMode.plain)

print(roundedValue1) // returns 0.684
print(roundedValue2) // returns 0.685
Run Code Online (Sandbox Code Playgroud)

#7.使用NSString init(format:arguments:)初始化程序

如果NSString要从舍入操作返回a ,使用NSString初始化程序是一种简单但有效的解决方案.

import Foundation

let roundedValue1 = NSString(format: "%.3f", 0.6844)
let roundedValue2 = NSString(format: "%.3f", 0.6849)
print(roundedValue1) // prints 0.684
print(roundedValue2) // prints 0.685
Run Code Online (Sandbox Code Playgroud)

#8.使用String init(format:_:)初始化程序

Swift的String类型与Foundation的NSString类是桥接的(你可以通过阅读Swift编程语言来了解它的更多信息).因此,您可以使用以下代码String从舍入操作返回a :

import Foundation

let roundedValue1 = String(format: "%.3f", 0.6844)
let roundedValue2 = String(format: "%.3f", 0.6849)
print(roundedValue1) // prints 0.684
print(roundedValue2) // prints 0.685
Run Code Online (Sandbox Code Playgroud)

#9.运用NumberFormatter

如果您希望String?从舍入操作中获得,请NumberFormatter提供高度可定制的解决方案.

import Foundation

let formatter = NumberFormatter()
formatter.numberStyle = NumberFormatter.Style.decimal
formatter.roundingMode = NumberFormatter.RoundingMode.halfUp
formatter.maximumFractionDigits = 3

let roundedValue1 = formatter.string(from: 0.6844)
let roundedValue2 = formatter.string(from: 0.6849)
print(String(describing: roundedValue1)) // prints Optional("0.684")
print(String(describing: roundedValue2)) // prints Optional("0.685")
Run Code Online (Sandbox Code Playgroud)

  • 很好的答案。我可能会在 #5 上建议您考虑使用 `Decimal`,它是免费桥接到 `NSDecimalNumber` 的。`Decimal` 是 Swift 的原生类型,为 `+`、`-` 等原生操作符提供了更优雅的支持。 (3认同)
  • 我很遗憾 `NumberFormatter` 是最后一个选项,而它应该是第一个向用户显示数字的选项。没有其他方法可以生成正确本地化的数字。 (2认同)

Cla*_*nas 91

在Swift 2.0和Xcode 7.2中:

let pi: Double = 3.14159265358979
String(format:"%.2f", pi)
Run Code Online (Sandbox Code Playgroud)

例:

在此输入图像描述


Ash*_*Ash 26

在Yogi的回答基础上,这是一个完成工作的Swift函数:

func roundToPlaces(value:Double, places:Int) -> Double {
    let divisor = pow(10.0, Double(places))
    return round(value * divisor) / divisor
}
Run Code Online (Sandbox Code Playgroud)


Kru*_*tel 20

这是完全有效的代码

Swift 3.0/4.0,Xcode 9.0 GM/9.2

let doubleValue : Double = 123.32565254455
self.lblValue.text = String(format:"%.f", doubleValue)
print(self.lblValue.text)
Run Code Online (Sandbox Code Playgroud)

输出 - 123

self.lblValue_1.text = String(format:"%.1f", doubleValue)
print(self.lblValue_1.text)
Run Code Online (Sandbox Code Playgroud)

输出 - 123.3

self.lblValue_2.text = String(format:"%.2f", doubleValue)
print(self.lblValue_2.text)
Run Code Online (Sandbox Code Playgroud)

输出 - 123.33

self.lblValue_3.text = String(format:"%.3f", doubleValue)
print(self.lblValue_3.text)
Run Code Online (Sandbox Code Playgroud)

输出 - 123.326

  • 一行?,好像 3 行;) (2认同)

Ram*_*ami 17

小数后面的特定数字的代码是:

var a = 1.543240952039
var roundedString = String(format: "%.3f", a)
Run Code Online (Sandbox Code Playgroud)

这里%.3f告诉swift将这个数字舍入到3个小数位.如果你想要双号,你可以使用这个代码:

// String为Double

var roundedString = Double(String(format: "%.3f", b))


jai*_*jan 16

在Swift 3.0和Xcode 8.0中:

extension Double {
    func roundTo(places: Int) -> Double {
        let divisor = pow(10.0, Double(places))
        return (self * divisor).rounded() / divisor
    }
}
Run Code Online (Sandbox Code Playgroud)

像这样使用此扩展,

let doubleValue = 3.567
let roundedValue = doubleValue.roundTo(places: 2)
print(roundedValue) // prints 3.56
Run Code Online (Sandbox Code Playgroud)


Nai*_*hta 16

Swift 4,Xcode 10

yourLabel.text =  String(format:"%.2f", yourDecimalValue)
Run Code Online (Sandbox Code Playgroud)

  • 不知道为什么这个可行的解决方案被否决了 (2认同)
  • 我没有投反对票,但我认为原因可能是因为这返回的是数字的字符串表示形式,而不是数字。如果这就是您所需要的,那很好,但您可能希望数字本身四舍五入以供进一步使用。OP 确实说了“当我打印时”,所以我确实认为在这种情况下这是一个可以接受的、简单的、干净的解决方案。 (2认同)

Geo*_*kos 15

使用内置的Foundation Darwin库

SWIFT 3

extension Double {
    func round(to places: Int) -> Double {
        let divisor = pow(10.0, Double(places))
        return Darwin.round(self * divisor) / divisor
    }
}
Run Code Online (Sandbox Code Playgroud)

用法:

let number:Double = 12.987654321
print(number.round(to: 3)) 
Run Code Online (Sandbox Code Playgroud)

产出:12.988


Mar*_*ong 9

一个方便的方法可以是使用Double类型的扩展

extension Double {
    var roundTo2f: Double {return Double(round(100 *self)/100)  }
    var roundTo3f: Double {return Double(round(1000*self)/1000) }
}
Run Code Online (Sandbox Code Playgroud)

用法:

let regularPie:  Double = 3.14159
var smallerPie:  Double = regularPie.roundTo3f  // results 3.142
var smallestPie: Double = regularPie.roundTo2f  // results 3.14
Run Code Online (Sandbox Code Playgroud)


Cab*_*e W 8

为了方便使用,我创建了一个扩展:

extension Double {
    var threeDigits: Double {
        return (self * 1000).rounded(.toNearestOrEven) / 1000
    }
    
    var twoDigits: Double {
        return (self * 100).rounded(.toNearestOrEven) / 100
    }
    
    var oneDigit: Double {
        return (self * 10).rounded(.toNearestOrEven) / 10
    }
}

var myDouble = 0.12345
print(myDouble.threeDigits)
print(myDouble.twoDigits)
print(myDouble.oneDigit)
Run Code Online (Sandbox Code Playgroud)

打印结果为:

0.123
0.12
0.1
Run Code Online (Sandbox Code Playgroud)

感谢其他答案的启发!


小智 7

这是一种长期的解决方法,如果您的需求稍微复杂一些,它可能会派上用场.您可以在Swift中使用数字格式化程序.

let numberFormatter: NSNumberFormatter = {
    let nf = NSNumberFormatter()
    nf.numberStyle = .DecimalStyle
    nf.minimumFractionDigits = 0
    nf.maximumFractionDigits = 1
    return nf
}()
Run Code Online (Sandbox Code Playgroud)

假设您要打印的变量是

var printVar = 3.567
Run Code Online (Sandbox Code Playgroud)

这将确保以所需的格式返回:

numberFormatter.StringFromNumber(printVar)
Run Code Online (Sandbox Code Playgroud)

这里的结果将是"3.6"(四舍五入).虽然这不是最经济的解决方案,但我给它是因为OP提到了打印(在这种情况下,String不是不合需要的),并且因为这个类允许设置多个参数.


小智 7

我会用

print(String(format: "%.3f", totalWorkTimeInHours))
Run Code Online (Sandbox Code Playgroud)

并将.3f更改为您需要的任意数量的十进制数


sta*_*Man 7

或者:

  1. 使用String(format:):

  2. 通过计算


Luk*_*z D 7

雨燕5

使用字符串方法

var yourDouble = 3.12345
//to round this to 2 decimal spaces i could turn it into string
let roundingString = String(format: "%.2f", myDouble)
let roundedDouble = Double(roundingString) //and than back to double
// result is 3.12 
Run Code Online (Sandbox Code Playgroud)

但使用扩展更容易被接受

extension Double {
    func round(to decimalPlaces: Int) -> Double {
        let precisionNumber = pow(10,Double(decimalPlaces))
        var n = self // self is a current value of the Double that you will round
        n = n * precisionNumber
        n.round()
        n = n / precisionNumber
        return n
    }
}
Run Code Online (Sandbox Code Playgroud)

然后你可以使用:

yourDouble.round(to:2)
Run Code Online (Sandbox Code Playgroud)


Nik*_*nko 6

这是一种更灵活的舍入到N位有效数字的算法

Swift 3解决方案

extension Double {
// Rounds the double to 'places' significant digits
  func roundTo(places:Int) -> Double {
    guard self != 0.0 else {
        return 0
    }
    let divisor = pow(10.0, Double(places) - ceil(log10(fabs(self))))
    return (self * divisor).rounded() / divisor
  }
}


// Double(0.123456789).roundTo(places: 2) = 0.12
// Double(1.23456789).roundTo(places: 2) = 1.2
// Double(1234.56789).roundTo(places: 2) = 1200
Run Code Online (Sandbox Code Playgroud)


Abu*_*oor 6

格式化double属性的最佳方法是使用Apple预定义方法.

mutating func round(_ rule: FloatingPointRoundingRule)
Run Code Online (Sandbox Code Playgroud)

FloatingPointRoundingRule是一个具有以下可能性的枚举

查点案例:

case awayFromZero舍 入到最接近的允许值,其大小大于或等于源的大小.

case down 舍入到小于或等于源的最近允许值.

case toNearestOrAwayFromZero舍 入到最接近的允许值; 如果两个值相等,则选择幅度更大的值.

case toNearestOrEven舍 入到最接近的允许值; 如果两个值相等,则选择偶数.

case toZero Round to the allowed allow value,其大小小于或等于source的值.

case up 舍入到大于或等于源的最近允许值.

var aNumber : Double = 5.2
aNumber.rounded(.up) // 6.0
Run Code Online (Sandbox Code Playgroud)


小智 6

将double值舍入为x的十进制数
NO.十进制后的数字

var x = 1.5657676754
var y = (x*10000).rounded()/10000
print(y)  // 1.5658 
Run Code Online (Sandbox Code Playgroud)
var x = 1.5657676754 
var y = (x*100).rounded()/100
print(y)  // 1.57 
Run Code Online (Sandbox Code Playgroud)
var x = 1.5657676754
var y = (x*10).rounded()/10
print(y)  // 1.6
Run Code Online (Sandbox Code Playgroud)


Rob*_*Rob 6

如果要对Double值进行舍入,可能需要使用Swift,Decimal因此在尝试使用这些舍入值进行数学运算时,不会引入任何可能出现的错误.如果使用Decimal,它可以准确地表示该舍入浮点值的十进制值.

所以你可以这样做:

extension Double {
    /// Convert `Double` to `Decimal`, rounding it to `scale` decimal places.
    ///
    /// - Parameters:
    ///   - scale: How many decimal places to round to. Defaults to `0`.
    ///   - mode:  The preferred rounding mode. Defaults to `.plain`.
    /// - Returns: The rounded `Decimal` value.

    func roundedDecimal(to scale: Int = 0, mode: NSDecimalNumber.RoundingMode = .plain) -> Decimal {
        var decimalValue = Decimal(self)
        var result = Decimal()
        NSDecimalRound(&result, &decimalValue, scale, mode)
        return result
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以Decimal像这样获得舍入值:

let foo = 427.3000000002
let value = foo.roundedDecimal(to: 2) // results in 427.30
Run Code Online (Sandbox Code Playgroud)

如果要使用指定的小数位数显示它(以及为用户当前的语言环境本地化字符串),可以使用NumberFormatter:

let formatter = NumberFormatter()
formatter.maximumFractionDigits = 2
formatter.minimumFractionDigits = 2

if let string = formatter.string(for: value) {
    print(string)
}
Run Code Online (Sandbox Code Playgroud)

  • 迄今为止最好的答案。 (2认同)
  • @vk.edward.li - 是的,应该警惕四舍五入小数点,因为像 4.81 这样的值根本无法用“Double”准确表示(它变成了“4.8099999999999996”)。但是我建议不要使用`description`(因为它采用的舍入没有记录并且可能会发生变化)。如果你真的想做十进制精确的数学,你应该完全避免使用“Double”,而应该直接使用“Decimal”(例如“Decimal(sign: .plus, exponent: -2, significand: 481)”或“Decimal” (string: "4.81")`。但不要使用`description`。 (2认同)

Mat*_*iti 6

这似乎在 Swift 5 中有效。

令人惊讶的是,目前还没有一个标准函数。

//通过四舍五入将 Double 截断至小数点后 n 位

extension Double {

    func truncate(to places: Int) -> Double {
    return Double(Int((pow(10, Double(places)) * self).rounded())) / pow(10, Double(places))
    }

}
Run Code Online (Sandbox Code Playgroud)


Pra*_*dha 6

该解决方案对我有用。XCode 13.3.1 和 Swift 5

extension Double {
    
    func rounded(decimalPoint: Int) -> Double {
        let power = pow(10, Double(decimalPoint))
       return (self * power).rounded() / power
    }
}
Run Code Online (Sandbox Code Playgroud)

测试:

print(-87.7183123123.rounded(decimalPoint: 3))
print(-87.7188123123.rounded(decimalPoint: 3))
print(-87.7128123123.rounded(decimalPoint: 3))
Run Code Online (Sandbox Code Playgroud)

结果:

-87.718
-87.719
-87.713
Run Code Online (Sandbox Code Playgroud)


yog*_*ogi 5

不是斯威夫特,但我相信你明白了.

pow10np = pow(10,num_places);
val = round(val*pow10np) / pow10np;
Run Code Online (Sandbox Code Playgroud)


vad*_*ian 5

在 iOS 15 / macOS 12 中引入了新的内联数字格式化程序。

没有任何舍入规则,它像学校教的那样舍入。语法

let value = 1.543240
let rounded = value.formatted(.number.precision(.fractionLength(2))))
Run Code Online (Sandbox Code Playgroud)

向下舍入为 1.54,并且

let value = 1.545240
let rounded = value.formatted(.number.precision(.fractionLength(2))))
Run Code Online (Sandbox Code Playgroud)

四舍五入到 1.55,fractionLength指定小数位数

要强制向下舍入,请添加舍入规则

let rounded = value.formatted(.number.rounded(rule: .down).precision(.fractionLength(2))))
Run Code Online (Sandbox Code Playgroud)