Featured image of post Swift 的數字處理

Swift 的數字處理

本文整理了處理數字常常遇到的情境


無條件進位

無條件進位至整數

1
2
3
4
5
6
7
extension Double {
  var ceilValue: Double {
      ceil(self)
  }
}
print(12.3.ceilValue)
//13.0

無條件進位至整數第 n 位

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
extension Double {
    func ceiling(toInteger integer: Int = 1) -> Double {
        let integer = integer - 1
        let numberOfDigits = pow(10.0, Double(integer))
        return Double(ceil(self / numberOfDigits)) * numberOfDigits
    }
}

123.12345.ceiling(toInteger: -1)
// print 123.13

(-123.12345).ceiling(toInteger: 0)
// print -123.1

123.12345.ceiling(toInteger: 2)
// print 130.0

(-123.12345).ceiling(toInteger: 1)
// print -123

無條件進位至小數第 n 位

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
extension Double {
    func ceiling(toDecimal decimal: Int) -> Double {
        let numberOfDigits = abs(pow(10.0, Double(decimal)))
        if self.sign == .minus {
            return Double(Int(self * numberOfDigits)) / numberOfDigits
        } else {
            return Double(ceil(self * numberOfDigits)) / numberOfDigits
        }
    }
}

123.12345.ceiling(toDecimal: 0)
//123.124

123.12345.ceiling(toDecimal: 3)
//123.124

(-123.12345).ceiling(toDecimal: 3)
//-123.123,因為 -123.123 在 y 軸的右邊

無條件捨去

無條件捨去至整數

1
2
3
4
5
6
7
extension Double {
  var intValue: Int {
    Int(self)
  }
}
print(12.3.intValue)
//12.0

無條件捨去至整數第 n 位

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
extension Double {
    func floor(toInteger integer: Int) -> Double {
        let integer = integer - 1
        let numberOfDigits = pow(10.0, Double(integer))
        return (self / numberOfDigits).rounded(.towardZero) * numberOfDigits
    }
}

print(123.123.floor(toInteger: 0))
// 123.10000000000001

print((-123.123).floor(toInteger: 1))
// -123.0

print(125.123.floor(toInteger: 2))
// 120.0

print((-125.123).floor(toInteger: 3))
// -100.0

無條件捨去至小數第 n 位

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
extension Double {
    func floor(toDecimal decimal: Int) -> Double {
        let numberOfDigits = pow(10.0, Double(decimal))
        return (self * numberOfDigits).rounded(.towardZero) / numberOfDigits
    }
}
print(123.123.floor(toDecimal: 0))
// 123.0

print((-123.123).floor(toDecimal: 1))
// -123.1

print(125.123.floor(toDecimal: 2))
// 125.12

print((-125.123).floor(toDecimal: 3))
// -125.123

四捨五入

四捨五入至整數

1
2
3
4
5
print(lround(11.5))
//12

print(round(11.5))
//12.0

四捨五入至整數第 n 位

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16

extension Double {
    func rounding(toInteger integer: Int) -> Double {
        let integer = integer - 1
        let numberOfDigits = pow(10.0, Double(integer))
        return (self / numberOfDigits).rounded(.toNearestOrAwayFromZero) * numberOfDigits
    }
}
print(124.141.rounding(toInteger: 1))
// 124.0
print(125.541.rounding(toInteger: 1))
// 126.0
print((-124.141).rounding(toInteger: 2))
// -120.0
print((-125.141).rounding(toInteger: 2))
// -130.0

四捨五入至小數第 n 位

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
extension Double {
    func rounding(toDecimal decimal: Int) -> Double {
        let numberOfDigits = pow(10.0, Double(decimal))
        return (self * numberOfDigits).rounded(.toNearestOrAwayFromZero) / numberOfDigits
    }
}


print(124.141.rounding(toDecimal: 1))
// 124.1
print(125.541.rounding(toDecimal: 1))
// 126.5
print((-124.141).rounding(toDecimal: 2))
// -124.14
print((-125.141).rounding(toDecimal: 2))
// -125.14

浮點數只取小數部分

有三種方式,結果都會是一樣

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
extension Double {
    var fraction: Double {
        self.truncatingRemainder(dividingBy: 1)
    }
    var fraction2: Double {
        var integer = 0.0
        let fraction = modf(self, &integer)
        return fraction
    }
    var fraction3: Double {
        let intX = Int(self)
        let fracPart = self - Double(intX)
        return fracPart
    }
}
print(123123.33.fraction)  //0.33000000000174623
print(123123.33.fraction2) //0.33000000000174623
print(123123.33.fraction3) //0.33000000000174623

浮點數只取整數部分

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
extension Double {
  var intValue: Int {
    Int(self)
  }
}
print(123.456.intValue)
//123

print(0.456.intValue)
//0

直接轉 Int 就能辦到

浮點數轉字串並指定小數點第 n 位

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
extension Double {
    func stringValue(_ toPosition: UInt) -> String {

        let doubleStr = String(format: "%.\(toPosition)f", self) // "3.14"
        return doubleStr
    }
}

print(123.456.stringValue(2))
//123.46

print(0.456.stringValue(1))
//0.5

%.2f 的 String format 方式預設是四捨五入的模式

千分位

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
extension Int {
    var comma: String {
        let prefix = self < 0 ? "-" : ""
        let numberFormatter = NumberFormatter()
        numberFormatter.numberStyle = .decimal
        numberFormatter.maximumFractionDigits = 0
        numberFormatter.locale = .init(identifier: "zh_Hant_TW")
        let final = numberFormatter.string(from: .init(integerLiteral: abs(self))) ?? ""
        return "\(prefix)\(final)"
    }
}
print(1000.comma) // 1,000
print((-1000).comma) // -1,000

主要是 NumberFormatter 的運用。

轉文字數字

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
extension String {
  var intValue: Int {
    int ?? 0
  }
  var int: Int? {
    Int(self)
  }
}
print("20".intValue) // 20
print("ABC".intValue) // 0

數字轉文字

1
2
3
4
5
6
extension Int {
  var stringValue: String {
    "\(self)"
  }
}
print(20.stringValue)

參考

dinostack.cc
使用 Hugo 建立
主題 StackJimmy 設計