Форматирование чисел с плавающей точкой: спецификатор точности в Swift
Использование String(format:) и современных возможностей Swift
Ты абсолютно прав, что String(format:) работает. Это наследие из Objective-C и C, и оно вполне корректно используется в Swift. Однако Swift предлагает более элегантные и типобезопасные способы форматирования чисел. Давай разберём все возможные подходы.
1. Классический String(format:)
Самый простой и понятный способ, если ты привык к printf-стилю:
let pi = 3.1415926535
let twoDecimals = String(format: "%.2f", pi) // "3.14"
let threeDecimals = String(format: "%.3f", pi) // "3.142"
let fourDecimals = String(format: "%.4f", pi) // "3.1416"
print(twoDecimals) // Вывод: 3.14
%.2f— 2 знака после запятой (округление).%.0f— без дробной части (целое).%6.2f— минимальная ширина 6 символов, 2 знака после запятой.
2. Современный способ: NumberFormatter
Этот подход более гибкий и учитывает локаль пользователя. Рекомендуется для UI (отображение цен, процентов):
import Foundation
let pi = 3.1415926535
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
formatter.maximumFractionDigits = 2
formatter.minimumFractionDigits = 2
formatter.locale = Locale.current // Учитывает региональные настройки
if let formatted = formatter.string(from: NSNumber(value: pi)) {
print(formatted) // "3.14" (или "3,14" для некоторых локалей)
}
maximumFractionDigits— максимальное количество знаков после запятой.minimumFractionDigits— минимальное (дополнит нулями, если нужно).- Можно настроить разделители тысяч, валюту и т.д.
3. Использование FloatingPoint протокола (Swift 5.5+)
Начиная с iOS 15 / macOS 12, можно использовать метод formatted() на числах:
import Foundation
let pi = 3.1415926535
let formatted = pi.formatted(.number.precision(.fractionLength(2)))
print(formatted) // "3.14"
Это самый «свифтовый» способ. Он полностью типобезопасен и читаем:
// Другие примеры:
let percent = 0.85
let percentFormatted = percent.formatted(.percent.precision(.fractionLength(0)))
print(percentFormatted) // "85%"
let currency = 1234.5
let currencyFormatted = currency.formatted(.currency(code: "USD"))
print(currencyFormatted) // "$1,234.50"
4. Интерполяция строк с specifier (Swift 5.0+)
Ты почти угадал! В Swift можно использовать интерполяцию с явным указанием спецификатора:
let pi = 3.1415926535
print("\(pi, specifier: "%.2f")") // "3.14"
Это работает, если импортировать Foundation (или UIKit/SwiftUI). Синтаксис немного необычный, но вполне валидный.
Итог
- Быстро и просто:
String(format: "%.2f", pi). - Для UI и локализации:
NumberFormatter. - Современно (iOS 15+):
pi.formatted(.number.precision(.fractionLength(2))). - Интерполяция:
"\(pi, specifier: "%.2f")".
Выбирай тот, который лучше подходит под твою задачу. Если ты пишешь под старые версии iOS — используй String(format:) или NumberFormatter.
Альтернативный подход: округление с помощью round() и Decimal
Иногда нужно не просто отформатировать строку, а получить точное число с определённой точностью для дальнейших вычислений. В таких случаях можно использовать округление:
let pi = 3.1415926535
let rounded = (pi * 100).rounded() / 100 // 3.14
print(rounded) // 3.14
Однако этот способ может давать погрешности из-за двоичного представления чисел с плавающей точкой. Для финансовых расчётов лучше использовать Decimal:
import Foundation
let pi = Decimal(string: "3.1415926535")!
var rounded = Decimal()
NSDecimalRound(&rounded, &pi, 2, .plain) // округление до 2 знаков
print(rounded) // 3.14
Этот подход гарантирует точность, так как Decimal работает с десятичной арифметикой. Комбинируй его с NumberFormatter для вывода:
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
formatter.maximumFractionDigits = 2
formatter.minimumFractionDigits = 2
let result = formatter.string(from: rounded as NSNumber)!
print(result) // "3.14"
Используй этот метод, если точность критична (например, деньги, научные расчёты).
Ответов пока нет.
Войдите чтобы оставить ответ