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

时间:2014-12-07 01:27:21

标签: ios swift double nstimeinterval

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

我有:

var totalWorkTimeInHours = (totalWorkTime/60/60)

totalWorkTime是第二个NSTimeInterval(double)。

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

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

29 个答案:

答案 0 :(得分:388)

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
    }
}


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
    }
}


返回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

答案 1 :(得分:331)

您可以使用Swift的round函数来完成此任务。

要以3位数精度对Double进行舍入,首先将其乘以1000,然后将其舍入并将舍入结果除以1000:

let x = 1.23556789
let y = Double(round(1000*x)/1000)
print(y)  // 1.236

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

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

What Every Computer Scientist Should Know About Floating-Point Arithmetic

答案 2 :(得分:269)

  

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

要将totalWorkTimeInHours舍入为3位进行打印,请使用带有String字符串的format构造函数:

print(String(format: "%.3f", totalWorkTimeInHours))

答案 3 :(得分:186)

使用Swift 5,根据您的需要,您可以选择 9个以下样式之一,以便从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

#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

#3。使用Darwin 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

#4。使用使用Darwin Doubleround函数构建的pow扩展自定义方法

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

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

#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

#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

#7。使用NSString init(format:arguments:)初始值设定项

如果您想从舍入操作返回NSString,使用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

#8。使用String init(format:_:)初始值设定项

Swift的String类型与Foundation的NSString类桥接。因此,您可以使用以下代码从舍入操作返回String

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

#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")

答案 4 :(得分:86)

在Swift 2.0和Xcode 7.2中:

let pi: Double = 3.14159265358979
String(format:"%.2f", pi)

示例:

enter image description here

答案 5 :(得分:26)

基于Yogi的回答,这是一个完成工作的Swift功能:

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

答案 6 :(得分:18)

这是完全有效的代码

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)

输出 - 123

 self.lblValue_1.text = String(format:"%.1f", doubleValue)
 print(self.lblValue_1.text)

输出 - 123.3

 self.lblValue_2.text = String(format:"%.2f", doubleValue)
 print(self.lblValue_2.text)

输出 - 123.33

 self.lblValue_3.text = String(format:"%.3f", doubleValue)
 print(self.lblValue_3.text)

输出 - 123.326

答案 7 :(得分:16)

小数点后的特定数字代码为:

var a = 1.543240952039
var roundedString = String(format: "%.3f", a)

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

  

//要加倍的字符串

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

答案 8 :(得分:15)

Swift 4,Xcode 10

yourLabel.text =  String(format:"%.2f", yourDecimalValue)

答案 9 :(得分:15)

在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
        }
    }

像这样使用此扩展程序,

let doubleValue = 3.567
let roundedValue = doubleValue.roundTo(places: 2)
print(roundedValue) // prints 3.56

答案 10 :(得分:9)

一种方便的方法是使用 Double

类型的扩展名
extension Double {
    var roundTo2f: Double {return Double(round(100 *self)/100)  }
    var roundTo3f: Double {return Double(round(1000*self)/1000) }
}

用法:

let regularPie:  Double = 3.14159
var smallerPie:  Double = regularPie.roundTo3f  // results 3.142
var smallestPie: Double = regularPie.roundTo2f  // results 3.14

答案 11 :(得分:9)

使用内置的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
    }

}

用法:

let number:Double = 12.987654321
print(number.round(to: 3)) 

输出:12.988

答案 12 :(得分:7)

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

let numberFormatter: NSNumberFormatter = {
    let nf = NSNumberFormatter()
    nf.numberStyle = .DecimalStyle
    nf.minimumFractionDigits = 0
    nf.maximumFractionDigits = 1
    return nf
}()

假设您要打印的变量是

var printVar = 3.567

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

numberFormatter.StringFromNumber(printVar)

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

答案 13 :(得分:7)

我会用

print(String(format: "%.3f", totalWorkTimeInHours))

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

答案 14 :(得分:6)

要么:

  1. 使用String(format:)

    • 使用Double格式说明符将String转换为%.3f,然后返回到Double

      Double(String(format: "%.3f", 10.123546789))!
      
    • 或扩展Double以处理N个小数位:

      extension Double {
          func rounded(toDecimalPlaces n: Int) -> Double {
              return Double(String(format: "%.\(n)f", self))!
          }
      }
      
  2. 通过计算

    • 乘以10 ^ 3,将其取整,然后除以10 ^ 3 ...

      (1000 * 10.123546789).rounded()/1000
      
    • 或扩展Double以处理N个小数位:

      extension Double {    
          func rounded(toDecimalPlaces n: Int) -> Double {
              let multiplier = pow(10, Double(n))
              return (multiplier * self).rounded()/multiplier
          }
      }
      

答案 15 :(得分: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
    }
}

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

let foo = 427.3000000002
let value = foo.roundedDecimal(to: 2) // results in 427.30

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

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

if let string = formatter.string(for: value) {
    print(string)
}

答案 16 :(得分:6)

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

mutating func round(_ rule: FloatingPointRoundingRule)

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

枚举案例

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

结案 舍入到小于或等于源的最接近允许值。

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

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

案件朝着Zero 舍入到最接近的允许值,其大小小于或等于源的值。

案例 舍入到最接近的允许值,该值大于或等于源。

var aNumber : Double = 5.2
aNumber.rounded(.up) // 6.0

答案 17 :(得分: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

答案 18 :(得分:5)

将double值舍入为x的十进制数
没有。小数后的数字

var x = 1.5657676754
var y = (x*10000).rounded()/10000
print(y)  // 1.5658 
var x = 1.5657676754 
var y = (x*100).rounded()/100
print(y)  // 1.57 
var x = 1.5657676754
var y = (x*10).rounded()/10
print(y)  // 1.6

答案 19 :(得分:5)

不是斯威夫特,但我确信你明白了。

pow10np = pow(10,num_places);
val = round(val*pow10np) / pow10np;

答案 20 :(得分:1)

//find the distance between two points
let coordinateSource = CLLocation(latitude: 30.7717625, longitude:76.5741449 )
let coordinateDestination = CLLocation(latitude: 29.9810859, longitude: 76.5663599)
let distanceInMeters = coordinateSource.distance(from: coordinateDestination)
let valueInKms = distanceInMeters/1000
let preciseValueUptoThreeDigit = Double(round(1000*valueInKms)/1000)
self.lblTotalDistance.text = "Distance is : \(preciseValueUptoThreeDigit) kms"

答案 21 :(得分:1)

我发现这可能是否有可能纠正用户的输入。也就是说,如果他们输入三位小数而不是两位小数金额。说1.111而不是1.11你能通过四舍五入来解决它吗?答案有很多原因,不是!有钱甚至0.001,最终会导致真正的支票簿出现问题。

这是一个在句点之后检查用户输入过多值的函数。但这将允许1,1.1和1.11。

假设已经检查了该值是否成功从String转换为Double。

//func need to be where transactionAmount.text is in scope

func checkDoublesForOnlyTwoDecimalsOrLess()->Bool{


    var theTransactionCharacterMinusThree: Character = "A"
    var theTransactionCharacterMinusTwo: Character = "A"
    var theTransactionCharacterMinusOne: Character = "A"

    var result = false

    var periodCharacter:Character = "."


    var myCopyString = transactionAmount.text!

    if myCopyString.containsString(".") {

         if( myCopyString.characters.count >= 3){
                        theTransactionCharacterMinusThree = myCopyString[myCopyString.endIndex.advancedBy(-3)]
         }

        if( myCopyString.characters.count >= 2){
            theTransactionCharacterMinusTwo = myCopyString[myCopyString.endIndex.advancedBy(-2)]
        }

        if( myCopyString.characters.count > 1){
            theTransactionCharacterMinusOne = myCopyString[myCopyString.endIndex.advancedBy(-1)]
        }


          if  theTransactionCharacterMinusThree  == periodCharacter {

                            result = true
          }


        if theTransactionCharacterMinusTwo == periodCharacter {

            result = true
        }



        if theTransactionCharacterMinusOne == periodCharacter {

            result = true
        }

    }else {

        //if there is no period and it is a valid double it is good          
        result = true

    }

    return result


}

答案 22 :(得分:1)

如果需要带数字值的Text元素,则为SwiftUI。

struct RoundedDigitText : View {
    let digits : Int
    let number : Double

    var body : some View {
        Text(String(format: "%.\(digits)f", number))
    }
}

答案 23 :(得分:1)

为避免浮动不完美,请使用Decimal

extension Float {
    func rounded(rule: NSDecimalNumber.RoundingMode, scale: Int) -> Float {
        var result: Decimal = 0
        var decimalSelf = NSNumber(value: self).decimalValue
        NSDecimalRound(&result, &decimalSelf, scale, rule)
        return (result as NSNumber).floatValue
    }
}

例如。
使用比例为2和.down的Float时,1075.58会四舍五入为1075.57
使用小数位数为2和.down

的1075.58舍入为1075.58

答案 24 :(得分:0)

Connect()

用法:

extension String{
  var roundedValue:String {
     return String(format: "%.3f", self)
}}

答案 25 :(得分:0)

您可以添加此扩展名:

extension Double {
    var clean: String {
        return self.truncatingRemainder(dividingBy: 1) == 0 ? String(format: "%.0f", self) : String(format: "%.2f", self)
    }
}

并这样称呼它:

let ex: Double = 10.123546789
print(ex.clean) // 10.12

答案 26 :(得分:0)

这似乎在Swift 5中有效。

令人惊讶的是,目前还没有标准功能。

//从舍入到双精度小数到n个小数位

extension Double {

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

}

答案 27 :(得分:0)

var n = 123.111222333
n = Double(Int(n * 10.0)) / 10.0

结果:n = 123.1

将10.0(小数点后1位)更改为100.0(小数点后2位),1000.0(小数点后3位)中的任意一个,依此类推,以获取小数点后所需的位数。

答案 28 :(得分:0)

如果你想在逗号后面只有 0 表示回合,请看下面这个例子:

extension Double {
    func isInteger() -> Any {
        let check = floor(self) == self
        if check {
            return Int(self)
        } else {
            return self
        }
    }
}

let toInt: Double = 10.0
let stillDouble: Double = 9.12

print(toInt.isInteger) // 10
print(stillDouble.isInteger) // 9.12