Округление числа Double до заданного количества знаков после запятой в Swift
Использование Foundation: round() с множителем
Самый простой и надёжный способ округления Double до заданного количества знаков после запятой — это умножить число на 10^n, применить стандартную функцию round() из Foundation, а затем разделить обратно. Такой подход сохраняет тип Double и не требует дополнительных библиотек.
import Foundation
func roundDouble(_ value: Double, toDecimalPlaces places: Int) -> Double {
let multiplier = pow(10.0, Double(places))
return round(value * multiplier) / multiplier
}
// Примеры использования:
let elapsedTime: Double = 3.14159265
let rounded = roundDouble(elapsedTime, toDecimalPlaces: 2)
print(rounded) // 3.14
print(type(of: rounded)) // Double
let largeNumber: Double = 12345.6789
let roundedLarge = roundDouble(largeNumber, toDecimalPlaces: 1)
print(roundedLarge) // 12345.7
Как это работает?
Функция pow(10.0, Double(places)) создаёт множитель: для 2 знаков это 100.0, для 3 — 1000.0 и т.д. Умножение сдвигает десятичную точку вправо, round() округляет до ближайшего целого, а деление возвращает точку на место. Результат — Double с нужной точностью.
Важные нюансы
- Плавающая точка: Из-за двоичного представления чисел с плавающей точкой результат может иметь микроскопические погрешности (например, 3.14 может храниться как 3.1400000000000001). Для отображения это не критично, но для строгих сравнений используйте
Double.ulpOfOneилиDecimal. - Отрицательные числа: Функция работает корректно с отрицательными значениями, так как
round()округляет по стандартным правилам (0.5 вверх). - Производительность:
pow()— это O(1) операция, поэтому функция подходит для массовых вычислений.
Расширение (Extension) для удобства
Вы можете добавить это поведение прямо к типу Double для более лаконичного синтаксиса:
extension Double {
func rounded(toDecimalPlaces places: Int) -> Double {
let multiplier = pow(10.0, Double(places))
return (self * multiplier).rounded() / multiplier
}
}
// Использование:
let price = 19.995
print(price.rounded(toDecimalPlaces: 2)) // 20.0 (округление вверх)
Альтернатива: NSDecimalNumber для финансовых расчётов
Если вам нужна абсолютная точность (например, для денег), используйте NSDecimalNumber с округлением по правилам банковского округления:
let decimalValue = NSDecimalNumber(value: 3.14159265)
let behavior = NSDecimalNumberHandler(
roundingMode: .plain,
scale: 2,
raiseOnExactness: false,
raiseOnOverflow: false,
raiseOnUnderflow: false,
raiseOnDivideByZero: false
)
let roundedDecimal = decimalValue.rounding(accordingToBehavior: behavior)
print(roundedDecimal.doubleValue) // 3.14
Этот метод гарантирует десятичную точность, но требует дополнительного кода и работает медленнее.
В итоге для большинства задач (отображение данных, вычисления с невысокой точностью) метод с round() и множителем — лучший выбор. Он прост, встроен в Foundation и не создаёт лишних преобразований.
Использование NumberFormatter для локализованного вывода
Если ваша цель — именно отображение числа пользователю с учётом локали (десятичный разделитель, формат тысяч), то лучше использовать NumberFormatter. Он не изменяет само число, но даёт строку, готовую для UI.
import Foundation
let value = 1234567.89123
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
formatter.minimumFractionDigits = 2
formatter.maximumFractionDigits = 2
if let formattedString = formatter.string(from: NSNumber(value: value)) {
print(formattedString) // "1,234,567.89" (для en_US) или "1 234 567,89" (для ru_RU)
}
Преимущества:
- Автоматически учитывает региональные настройки устройства.
- Поддерживает группировку разрядов (тысячи, миллионы).
- Не изменяет исходное число.
Недостатки: Возвращает строку, а не Double. Если вам нужно число для дальнейших вычислений, используйте первый ответ (с round()).
Для простого округления без локализации можно использовать String(format:), но помните, что это тоже строка:
let roundedString = String(format: "%.2f", value) // "1234567.89"
Выбирайте подход в зависимости от задачи: для математики — первый способ, для интерфейса — NumberFormatter.
Ответов пока нет.
Войдите чтобы оставить ответ
Блоги