← Назад к вопросам

В чем разница между хранением чисел Double и Decimal?

2.2 Middle🔥 181 комментариев
#Язык Swift

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI5 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Разница между Double и Decimal в iOS разработке

Основное различие между Double (число с плавающей точкой двойной точности) и Decimal (десятичное число с фиксированной точкой) заключается в их представлении чисел, точности и области применения, особенно критичной при работе с финансовыми расчетами.

Представление в памяти и точность

Double использует формат с плавающей точкой согласно стандарту IEEE 754:

// Double: 64 бита (1 знак, 11 экспонента, 52 мантисса)
let doubleValue: Double = 0.1 + 0.2 // Результат: 0.30000000000000004
print(doubleValue) // Выводит неточное значение

Decimal использует десятичное представление с фиксированной точкой:

// Decimal: 128 бита (знак, экспонента, мантисса в десятичной системе)
import Foundation

let decimalValue = Decimal(0.1) + Decimal(0.2) // Результат: 0.3
print(decimalValue) // Точно 0.3

Ключевые отличия

1. Точность и ошибки округления

  • Double: Имеет двоичное представление, что приводит к ошибкам округления при работе с десятичными дробями
  • Decimal: Сохраняет точное десятичное представление, идеально подходит для финансовых операций

2. Производительность

  • Double: Аппаратно ускорен, операции выполняются значительно быстрее
  • Decimal: Программная реализация, операции медленнее в 10-100 раз

3. Диапазон значений

  • Double: Огромный диапазон (~1.8×10³⁰⁸), но с ограниченной десятичной точностью
  • Decimal: Меньший диапазон (~7.9×10²⁸), но с точностью до 38 десятичных знаков

Практическое применение

Когда использовать Double:

  • Научные вычисления
  • Графика и игры
  • Геолокационные расчеты
  • Ситуации, где важна производительность
// Пример использования Double
func calculateDistance(lat1: Double, lon1: Double, lat2: Double, lon2: Double) -> Double {
    // Географические расчеты - Double оптимален
    let earthRadius: Double = 6371.0
    // ... вычисления расстояния
    return distance
}

Когда использовать Decimal:

  • Финансовые приложения (деньги, цены, налоги)
  • Бухгалтерские системы
  • Любые расчеты, где важна точность до копейки/цента
  • Системы, работающие с законодательно установленными ставками
// Пример использования Decimal для финансов
struct Money {
    let amount: Decimal
    let currency: Currency
    
    func calculateTax(rate: Decimal) -> Money {
        // Точный расчет налога без ошибок округления
        let tax = amount * rate / Decimal(100)
        return Money(amount: tax, currency: currency)
    }
}

Пример проблемы с Double и решение через Decimal

// Проблема с Double
let prices: [Double] = [0.1, 0.2, 0.3]
let totalDouble = prices.reduce(0, +)
print("Double total: \(totalDouble)") // Может быть 0.6000000000000001

// Решение с Decimal
let decimalPrices: [Decimal] = [0.1, 0.2, 0.3].map { Decimal($0) }
let totalDecimal = decimalPrices.reduce(0, +)
print("Decimal total: \(totalDecimal)") // Точно 0.6

Особенности реализации в Swift/Foundation

Decimal реализован в Foundation как структура:

// NSDecimalNumber (Objective-C) и Decimal (Swift)
import Foundation

// Создание Decimal
let decimalFromString = Decimal(string: "123.45") // Опциональный
let decimalFromDouble = Decimal(123.45) // Может потерять точность
let decimalFromInteger = Decimal(integerLiteral: 100)

// Арифметические операции
var result = Decimal()
NSDecimalAdd(&result, &decimalFromInteger, &decimalFromInteger, .plain)

Рекомендации по использованию

  1. Для денежных операций всегда используйте Decimal
  2. Конвертируйте Double в Decimal как можно раньше в финансовых цепочках
  3. Используйте NSDecimalNumberHandler для контроля округления:
let handler = NSDecimalNumberHandler(
    roundingMode: .bankers,
    scale: 2, // два знака после запятой
    raiseOnExactness: false,
    raiseOnOverflow: false,
    raiseOnUnderflow: false,
    raiseOnDivideByZero: false
)
  1. Храните денежные значения в минимальных единицах (копейках, центах) как целые числа, если требуется максимальная производительность

Производительность: сравнительная таблица

ОперацияDoubleDecimal
Сложение~1 наносекунда~100 наносекунд
Умножение~3 наносекунды~150 наносекунд
Деление~10 наносекунд~200 наносекунд

Заключение

Выбор между Double и Decimal — это компромисс между производительностью и точностью. Для финансовых приложений, где каждая копейка имеет значение, Decimal — единственно правильный выбор. Для научных вычислений, компьютерной графики и других областей, где важна скорость и приемлемы небольшие погрешности, Double остается оптимальным решением. Современные iOS-разработчики должны понимать эти различия и выбирать тип данных осознанно, исходя из требований конкретной задачи.

В чем разница между хранением чисел Double и Decimal? | PrepBro