【Swift】よく使いそうな String の format

プログラミング言語によって違うのよ、これが。

Swift の String()。


👉 init(format:_:) | Apple Developer Documentation hatena-bookmark

よく使われてるやつ。GitHub 調べ。


[

  String(format: "%02x", 255),
  // ff

  String(format: "%02X", 170),
  // AA

  String(format: "%02d", 1),
  // 01

  String(format: "% 5d", 2),
  //     2

  String(format: "%.2f", 1.2),
  // 1.20

  String(format: "%.2f", 1.204),
  // 1.20

  String(format: "%.2f", 1.205),
  // 1.21

  String(format: "%.0f", 1.23),
  // 1

  String(format: "%f", 3.12),
  // 3.120000

  String(format: "%+.2f", -123.5),
  // -123.50

  String(format: "%p", 3),
  // 0x3

  String(format: "%@", "x"),
  // x

  String(format: "%2$@ %1$@", "world", "Hello")
  // Hello world

].forEach {
  print($0)
}

知っておくだけで便利です。

👉 String Format Specifiers hatena-bookmark
👉 String Format Specifiers hatena-bookmark
👉 What are the supported Swift String format specifiers? - Stack Overflow hatena-bookmark


【Swift】少数の丸め方あれこれ - rounded()

こんなにあったのですか。


5.2
.rounded() 5.0
.rounded(.down) 5.0
.rounded(.up) 6.0
.rounded(.towardZero) 5.0
.rounded(.awayFromZero) 6.0
.rounded(.toNearestOrEven) 5.0
.rounded(.toNearestOrAwayFromZero) 5.0

5.5
.rounded() 6.0
.rounded(.down) 5.0
.rounded(.up) 6.0
.rounded(.towardZero) 5.0
.rounded(.awayFromZero) 6.0
.rounded(.toNearestOrEven) 6.0
.rounded(.toNearestOrAwayFromZero) 6.0

-5.2
.rounded() -5.0
.rounded(.down) -6.0
.rounded(.up) -5.0
.rounded(.towardZero) -5.0
.rounded(.awayFromZero) -6.0
.rounded(.toNearestOrEven) -5.0
.rounded(.toNearestOrAwayFromZero) -5.0

-5.5
.rounded() -6.0
.rounded(.down) -6.0
.rounded(.up) -5.0
.rounded(.towardZero) -5.0
.rounded(.awayFromZero) -6.0
.rounded(.toNearestOrEven) -6.0
.rounded(.toNearestOrAwayFromZero) -6.0

0.51
.rounded() 1.0
.rounded(.down) 0.0
.rounded(.up) 1.0
.rounded(.towardZero) 0.0
.rounded(.awayFromZero) 1.0
.rounded(.toNearestOrEven) 1.0
.rounded(.toNearestOrAwayFromZero) 1.0

0.0
.rounded() 0.0
.rounded(.down) 0.0
.rounded(.up) 0.0
.rounded(.towardZero) 0.0
.rounded(.awayFromZero) 0.0
.rounded(.toNearestOrEven) 0.0
.rounded(.toNearestOrAwayFromZero) 0.0

0.03
.rounded() 0.0
.rounded(.down) 0.0
.rounded(.up) 1.0
.rounded(.towardZero) 0.0
.rounded(.awayFromZero) 1.0
.rounded(.toNearestOrEven) 0.0
.rounded(.toNearestOrAwayFromZero) 0.0

1.001
.rounded() 1.0
.rounded(.down) 1.0
.rounded(.up) 2.0
.rounded(.towardZero) 1.0
.rounded(.awayFromZero) 2.0
.rounded(.toNearestOrEven) 1.0
.rounded(.toNearestOrAwayFromZero) 1.0

👉 rounded(_:) | Apple Developer Documentation hatena-bookmark
👉 round() | Apple Developer Documentation hatena-bookmark
👉 FloatingPointRoundingRule | Apple Developer Documentation hatena-bookmark

 

🧑‍💻 チャートにしてみる

視覚化してみると全然ちげえ !


import SwiftUI
struct Chart: View {
var function: (Double) -> Double
var by: Double
private let height = 20.0
private var data: [Double] {
stride(from: -3.0, to: 3.0 + by , by: by)
.map { $0 }
}
var body: some View {
ZStack {
ForEach(data, id: \.self) { n in
Rectangle()
.fill(Color.data[Int(function(n)) + 3])
.frame(width: 50 * by, height: height)
.position(CGPoint(x: 50 * n + 150, y: height / 2))
}
}
}
}
struct TestRounded: View {
var body: some View {
ZStack {
VStack {
ZStack {
LinearGradient(colors: Color.data, startPoint: .leading, endPoint: .trailing)
.frame(height: 20)
ForEach(0 ... 6, id: \.self) { i in
Text("\(i - 3)")
.foregroundStyle(.background)
.padding(.vertical, 4)
.padding(.horizontal)
.background(Color.data[i])
.position(CGPoint(x: 50 * i, y: -15))
}
}
Text("rounded()")
Text("rounded(.toNearestOrAwayFromZero)")
Text("schoolbook rounding")
Chart(function: { $0.rounded() }, by: 0.01)
//Chart(function: { $0.rounded(.toNearestOrAwayFromZero) }, by: 0.01)
Text("rounded(.down)")
Chart(function: { $0.rounded(.down) }, by: 0.01)
Text("rounded(.up)")
Chart(function: { $0.rounded(.up) }, by: 0.01)
Text("rounded(.towardZero)")
Chart(function: { $0.rounded(.towardZero) }, by: 0.01)
Text("rounded(.awayFromZero)")
Chart(function: { $0.rounded(.awayFromZero) }, by: 0.01)
Text("rounded(.toNearestOrEven)")
Text("bankers rounding")
Chart(function: { $0.rounded(.toNearestOrEven) }, by: 0.01)
}
.font(.caption2)
.background()
ForEach(0 ... 120, id: \.self) { j in
ForEach(0 ... 60, id: \.self) { i in
let size = i % 10 == 0 ? 2.0 : 1.0
Circle()
.fill(.gray)
.frame(width: size, height: size)
.position(CGPoint(x: 5 * i, y: 5 * j))
}
}
}
.frame(width: 300, height: 600)
.padding()
.onAppear {
// rounded(_:) | Apple Developer Documentation
// https://developer.apple.com/documentation/swift/double/rounded(_:)
// FloatingPointRoundingRule | Apple Developer Documentation
// https://developer.apple.com/documentation/swift/floatingpointroundingrule
[5.2, 5.5, -5.2, -5.5, 0.51, 0.0, 0.03, 1.001]
.forEach {
print($0)
print(".rounded()", $0.rounded())
print(".rounded(.down)", $0.rounded(.down))
print(".rounded(.up)", $0.rounded(.up))
print(".rounded(.towardZero)", $0.rounded(.towardZero))
print(".rounded(.awayFromZero)", $0.rounded(.awayFromZero))
print(".rounded(.toNearestOrEven)", $0.rounded(.toNearestOrEven))
print(".rounded(.toNearestOrAwayFromZero)", $0.rounded(.toNearestOrAwayFromZero))
print()
}
}
}
}
fileprivate extension Color {
static var data: [Color] {
[.blue, .green, .red, .black, .red, .green, .blue]
}
}
#Preview {
TestRounded()
}

 

🧑‍💻 まとめ

僕たちが日頃使っている四捨五入は、


.rounded()

で、


.rounded(.toNearestOrAwayFromZero)

のことと同じで、

「schoolbook rounding (教科書丸め)」

と呼ばれているようです。

「bankers rounding (銀行丸め)」

とか、要領よく出来てるんですね !

👉 端数処理 - Wikipedia hatena-bookmark

ちなみに「四捨五入」って多すぎ。

👉 Rounding a double value to x number of decimal places in swift - Stack Overflow hatena-bookmark



【Swift】Color の RGB + Opacity の数値を求める

カラーピッカーの

スポイドで

色を確認してたけど、

なんか、あやしい。


数値化してスッキリしたい。

 

🎨 Color から赤、緑、青の値を読み取る


struct ContentView: View {
  @Environment(\.self) var environment
  @State private var color = Color.red
  @State private var resolvedColor: Color.Resolved?

  var body: some View {
    VStack {
      ColorPicker("Select your favorite color", selection: $color)

      if let resolvedColor {
        Text("Red: \(resolvedColor.red)")
        Text("Green: \(resolvedColor.green)")
        Text("Blue: \(resolvedColor.blue)")
        Text("Opacity: \(resolvedColor.opacity)")
      }
    }
    .padding()
    .onChange(of: color, initial: true, getColor)
  }

  func getColor() {
    resolvedColor = color.resolve(in: environment)
  }
}

👉 How to read the red, green, and blue values from a Color - a free SwiftUI by Example tutorial hatena-bookmark

ビルトインの ColorPicker で取得した色を数字化して表示していますね。

分かりやすい !

 

🎨 小数点以下3桁に丸める

ついでに、

小数点以下4桁目を丸めて3桁にして、

0で埋める。


String(format:"%.3f", (0.123456 * 1000).rounded() / 1000)
// 0.123

👉 【Swift】2024年5月版 四捨五入と小数点と0埋め hatena-bookmark

てか、String のみで四捨五入できる、とか!

👉 Rounding a double value to x number of decimal places in swift - Stack Overflow hatena-bookmark

 

🎨 まとめ

これらをまとめて整理しておきます。


import SwiftUI
struct TestColorValues: View {
var color: Color
@Environment(\.self) private var environment
private var resolved: Color.Resolved {
color.resolve(in: environment)
}
var body: some View {
VStack {
Text("\(resolved)")
Text(String(format: "R: %.3f", resolved.red))
Text(String(format: "G: %.3f", resolved.green))
Text(String(format: "B: %.3f", resolved.blue))
Text(String(format: "O: %.3f", resolved.opacity))
}
.monospaced()
.padding()
.background(color)
}
}
#Preview("TestColorValues") {
VStack {
TestColorValues(color: Color(.secondarySystemBackground))
.environment(\.colorScheme, .light)
TestColorValues(color: Color(.secondarySystemBackground))
.environment(\.colorScheme, .dark)
}
}

Light / Dark 共、

数字が同じになりました。

なるほど、

Dynamic System Color というのは、

environment を見ながら色を変化させているのか !

変化させていたのだ !