Swift 3
currency formatting
double to currency
Swift programming
iOS development

How to format a Double into Currency - Swift 3

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

To format a Double as currency in Swift, use NumberFormatter with numberStyle = .currency. It automatically applies the correct currency symbol, decimal separator, grouping separator, and decimal places based on the user's locale. For Swift 5.5+ (iOS 15+), the formatted(.currency(code:)) API is even simpler. Avoid manual string interpolation like "$\(String(format: "%.2f", amount))" — it ignores locale, breaks for non-USD currencies, and uses the wrong separators for many regions.

NumberFormatter (All Swift Versions)

swift
1let amount = 1234.56
2
3let formatter = NumberFormatter()
4formatter.numberStyle = .currency
5
6let formatted = formatter.string(from: NSNumber(value: amount))
7// US locale: "$1,234.56"
8// German locale: "1.234,56 €"
9// Japanese locale: "¥1,235"

NumberFormatter uses the device's current locale by default. It handles currency symbols, grouping separators, decimal separators, and the number of fraction digits automatically.

Specifying a Locale

swift
1let amount = 1234.56
2
3// US Dollar
4let usFormatter = NumberFormatter()
5usFormatter.numberStyle = .currency
6usFormatter.locale = Locale(identifier: "en_US")
7print(usFormatter.string(from: NSNumber(value: amount))!)
8// "$1,234.56"
9
10// Euro (Germany)
11let deFormatter = NumberFormatter()
12deFormatter.numberStyle = .currency
13deFormatter.locale = Locale(identifier: "de_DE")
14print(deFormatter.string(from: NSNumber(value: amount))!)
15// "1.234,56 €"
16
17// Yen (Japan)
18let jpFormatter = NumberFormatter()
19jpFormatter.numberStyle = .currency
20jpFormatter.locale = Locale(identifier: "ja_JP")
21print(jpFormatter.string(from: NSNumber(value: amount))!)
22// "¥1,235" (no decimal places for yen)
23
24// Pound (UK)
25let ukFormatter = NumberFormatter()
26ukFormatter.numberStyle = .currency
27ukFormatter.locale = Locale(identifier: "en_GB")
28print(ukFormatter.string(from: NSNumber(value: amount))!)
29// "£1,234.56"

Specifying a Currency Code

To show a specific currency regardless of locale:

swift
1let formatter = NumberFormatter()
2formatter.numberStyle = .currency
3formatter.currencyCode = "EUR"  // ISO 4217 currency code
4formatter.locale = Locale(identifier: "en_US")
5
6print(formatter.string(from: NSNumber(value: 1234.56))!)
7// "€1,234.56" (Euro symbol with US formatting)

Formatted API (iOS 15+ / Swift 5.5+)

swift
1let amount = 1234.56
2
3// Uses device locale
4let formatted = amount.formatted(.currency(code: "USD"))
5// "$1,234.56"
6
7// Specific locale
8let euroFormatted = amount.formatted(
9    .currency(code: "EUR")
10    .locale(Locale(identifier: "de_DE"))
11)
12// "1.234,56 €"
13
14// No fraction digits
15let yenFormatted = amount.formatted(
16    .currency(code: "JPY")
17    .precision(.fractionLength(0))
18)
19// "¥1,235"

Reusable Extension

swift
1extension Double {
2    func toCurrency(locale: Locale = .current) -> String {
3        let formatter = NumberFormatter()
4        formatter.numberStyle = .currency
5        formatter.locale = locale
6        return formatter.string(from: NSNumber(value: self)) ?? "$0.00"
7    }
8
9    func toCurrency(code: String, locale: Locale = .current) -> String {
10        let formatter = NumberFormatter()
11        formatter.numberStyle = .currency
12        formatter.currencyCode = code
13        formatter.locale = locale
14        return formatter.string(from: NSNumber(value: self)) ?? "$0.00"
15    }
16}
17
18// Usage
19let price = 99.99
20print(price.toCurrency())                                    // "$99.99" (US locale)
21print(price.toCurrency(code: "GBP"))                        // "£99.99"
22print(price.toCurrency(locale: Locale(identifier: "fr_FR"))) // "99,99 €"

Customizing Decimal Places

swift
1let formatter = NumberFormatter()
2formatter.numberStyle = .currency
3formatter.minimumFractionDigits = 0
4formatter.maximumFractionDigits = 0
5
6print(formatter.string(from: NSNumber(value: 1234.56))!)
7// "$1,235" (rounded, no decimals)
8
9// Force 3 decimal places
10formatter.minimumFractionDigits = 3
11formatter.maximumFractionDigits = 3
12print(formatter.string(from: NSNumber(value: 1234.5))!)
13// "$1,234.500"

Using in SwiftUI

swift
1import SwiftUI
2
3struct PriceView: View {
4    let amount: Double
5
6    var body: some View {
7        Text(amount, format: .currency(code: "USD"))
8            .font(.title)
9    }
10}
11
12// With a TextField for currency input
13struct PriceInputView: View {
14    @State private var price: Double = 0
15
16    var body: some View {
17        TextField("Price", value: $price,
18                  format: .currency(code: "USD"))
19            .keyboardType(.decimalPad)
20    }
21}

Common Pitfalls

  • Using string interpolation instead of NumberFormatter: "$\(String(format: "%.2f", amount))" hardcodes the dollar sign and uses . as the decimal separator. This is incorrect for most non-US locales where the comma is the decimal separator and the currency symbol differs or appears after the number.
  • Creating a new NumberFormatter on every call: NumberFormatter is expensive to initialize. In table views or collection views, create the formatter once and reuse it. Store it as a property or use a static instance.
  • Forgetting that Double has floating-point precision issues: 0.1 + 0.2 is not exactly 0.3 in floating point. For financial calculations, use Decimal or NSDecimalNumber instead of Double to avoid rounding errors that appear in formatted output.
  • Hardcoding a locale instead of using .current: Hardcoding Locale(identifier: "en_US") forces US formatting for all users. Use Locale.current unless you specifically need a fixed locale (like displaying prices in a specific currency for all users).
  • Not handling the optional return from formatter.string(from:): NumberFormatter.string(from:) returns an optional String?. If the value is NaN or infinity, it returns nil. Always provide a fallback with ?? "$0.00" or use a guard statement.

Summary

  • Use NumberFormatter with .currency style for locale-aware currency formatting
  • Use .formatted(.currency(code: "USD")) on iOS 15+ for a concise one-liner
  • Set currencyCode to format a specific currency regardless of locale
  • Create a reusable Double extension to avoid duplicating formatter setup
  • Use Decimal instead of Double for financial calculations to avoid floating-point rounding errors

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.