关于ios:在swift中将double值舍入为x个小数位数

Rounding a double value to x number of decimal places in swift

有人能告诉我如何用swift将一个双精度的值四舍五入到小数位数X吗?

我有:

1
var totalWorkTimeInHours = (totalWorkTime/60/60)

其中totalWorkTime是秒的一个非时间间隔(双倍)。

totalWorkTimeInHours会给我时间,但它给了我如此长的时间,精确的数字,例如1.543240952039……

当我打印totalWorkTimeInHours时,我该如何把它四舍五入到1.543?


Swift 2的扩展

更通用的解决方案是以下扩展,它与Swift 2和iOS 9一起工作:

1
2
3
4
5
6
7
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
    }
}

< BR>

SWIFT 3扩展

在Swift 3中,round替换为rounded

1
2
3
4
5
6
7
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
    }
}

< BR>返回四舍五入到四位小数的示例:

1
2
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


您可以使用Swift的round功能来完成这项工作。

要用3位精度对Double进行四舍五入,首先将其乘以1000,四舍五入并将四舍五入的结果除以1000:

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

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

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

每一个计算机科学家都应该知道什么是浮点运算


How do I round this down to, say, 1.543 when I print totalWorkTimeInHours?

要将totalWorkTimeInHours四舍五入到3位进行打印,请使用String构造函数,该构造函数采用format字符串:

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


使用Swift 5,根据您的需要,您可以选择以下9种样式中的一种,以便从Double获得一个四舍五入的结果。

1。使用FloatingPointrounded()方法

在最简单的情况下,您可以使用Doubleround()方法。

1
2
3
4
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。使用FloatingPointrounded(_:)方法

1
2
3
4
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。使用达尔文round函数

基金会通过达尔文提供了一个EDCOX1×3函数。

1
2
3
4
5
6
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。使用由达尔文roundpow函数构建的Double扩展自定义方法

如果您想多次重复前面的操作,重构代码是一个好主意。

1
2
3
4
5
6
7
8
9
10
11
12
13
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。使用NSDecimalNumberrounding(accordingToBehavior:)方法

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

1
2
3
4
5
6
7
8
9
10
11
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(_:_:_:_:)函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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。使用NSStringinit(format:arguments:)初始值设定项

如果要从舍入操作返回NSString,使用NSString初始值设定项是一个简单但有效的解决方案。

1
2
3
4
5
6
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。使用Stringinit(format:_:)初始值设定项

SWIFT的EDOCX1×1类型是用基金会的EDCOX1×26类桥接的。因此,可以使用以下代码从舍入操作返回String

1
2
3
4
5
6
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提供了一个高度可定制的解决方案。

1
2
3
4
5
6
7
8
9
10
11
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")


在Swift 2.0和Xcode 7.2中:

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

例子:

enter image description here


基于Yogi的答案,这里有一个快速的功能来完成这项工作:

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

这是完全有效的代码

swift 3.0/4.0,xcode 9.0 gm/9.2

1
2
3
 let doubleValue : Double = 123.32565254455
 self.lblValue.text = String(format:"%.f", doubleValue)
 print(self.lblValue.text)

输出- 123

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

输出- 123.3

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

输出- 123.33

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

输出-123.326


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

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

这里,%.3f告诉Swift将这个数字四舍五入到小数点后3位。如果要双位数,可以使用此代码:

// String to Double

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


在Swift 3.0和Xcode 8.0中:

1
2
3
4
5
6
 extension Double {
        func roundTo(places: Int) -> Double {
            let divisor = pow(10.0, Double(places))
            return (self * divisor).rounded() / divisor
        }
    }

像这样使用这个扩展名,

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


Swift 4,xcode 10

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


一个方便的方法是使用double类型的扩展

1
2
3
4
extension Double {
    var roundTo2f: Double {return Double(round(100 *self)/100)  }
    var roundTo3f: Double {return Double(round(1000*self)/1000) }
}

用途:

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

使用内置的基础达尔文库

斯威夫特3

1
2
3
4
5
6
7
8
extension Double {

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

}

用途:

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

输出:12.988


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

1
2
3
4
5
6
7
let numberFormatter: NSNumberFormatter = {
    let nf = NSNumberFormatter()
    nf.numberStyle = .DecimalStyle
    nf.minimumFractionDigits = 0
    nf.maximumFractionDigits = 1
    return nf
}()

假设要打印的变量是

1
var printVar = 3.567

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

1
numberFormatter.StringFromNumber(printVar)

因此,这里的结果将是"3.6"(四舍五入)。虽然这不是最经济的解决方案,但我给出它是因为上面提到的打印(在这种情况下,字符串不是不可取的),并且因为这个类允许设置多个参数。


我会用

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

把.3f改成你需要的十进制数。


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

1
mutating func round(_ rule: FloatingPointRoundingRule)

floatingPointRoundingRule是一个枚举,具有以下可能性

枚举事例:

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

病案下来四舍五入到小于或等于源的最近允许值。

从零开始存储案例色调四舍五入到最接近的允许值;如果两个值相等,则选择幅度较大的值。

储存箱色调四舍五入到最接近的允许值;如果两个值相等,则选择偶数。

零度情况四舍五入到最接近的允许值,该值的大小小于或等于源的大小。

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

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

如果要对Double值进行四舍五入,可能需要使用swift Decimal,这样在尝试使用这些四舍五入值进行数学计算时,就不会引入任何可能出现的错误。如果您使用Decimal,它可以准确地表示该四舍五入浮点值的十进制值。

所以你可以这样做:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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值,如下所示:

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

如果要用指定的小数位数(以及用户当前区域设置的字符串本地化)显示它,可以使用NumberFormatter

1
2
3
4
5
6
7
let formatter = NumberFormatter()
formatter.maximumFractionDigits = 2
formatter.minimumFractionDigits = 2

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


要么:

  • 使用String(format:)

    • %.3f格式说明符将Double打字到String,然后返回Double

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

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

    • 乘以10^3,四舍五入,然后除以10^3…

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

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

  • 这是一种更为灵活的算法,可以四舍五入到n个有效数字

    Swift 3解决方案

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    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

    不是很快,但我相信你会明白的。

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


    将一个双精度值四舍五入到小数位数X小数后位数

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


    我发现这个问题是想知道是否可以纠正用户的输入。也就是说,如果他们输入三位小数,而不是两位,则表示一美元金额。比如说1.111而不是1.11,你能通过四舍五入来修正它吗?有很多原因的答案是否定的!如果有了钱,任何超过0.001的东西最终都会在真正的支票簿中造成问题。

    下面是一个函数,用于检查用户输入的值在该时间段之后是否过多。但允许1、1.1和1.11。

    假定已检查该值是否已成功从字符串转换为double。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    //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


    }

    1
    2
    3
    4
    5
    6
    7
    //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"

    您可以添加此扩展名:

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

    这样称呼它:

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

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

    用途:

    1
    totalWorkTimeInHours.roundedValue