2017-01-09 74 views
15

我是Swift編程的新手,我一直在Xcode 8.2中創建一個簡單的小費計算器應用程序,我在下面的IBAction中設置了我的計算。但是,當我真正運行我的應用程序並輸入一個數量來計算(如23.45)時,它會出現超過2個小數位。在這種情況下,我如何格式化爲.currency如何將一個Double格式化爲貨幣 - Swift 3

@IBAction func calculateButtonTapped(_ sender: Any) { 

    var tipPercentage: Double { 

     if tipAmountSegmentedControl.selectedSegmentIndex == 0 { 
      return 0.05 
     } else if tipAmountSegmentedControl.selectedSegmentIndex == 1 { 
      return 0.10 
     } else { 
      return 0.2 
     } 
    } 

    let billAmount: Double? = Double(userInputTextField.text!) 

    if let billAmount = billAmount { 
     let tipAmount = billAmount * tipPercentage 
     let totalBillAmount = billAmount + tipAmount 

     tipAmountLabel.text = "Tip Amount: $\(tipAmount)" 
     totalBillAmountLabel.text = "Total Bill Amount: $\(totalBillAmount)" 
    } 
} 

回答

25

,如果你想迫使貨幣$您可以使用此字符串初始化:

String(format: "Tip Amount: $%.02f", tipAmount) 

如果你希望它是完全依賴於設備的區域設置,您應該使用NumberFormatter。這將考慮貨幣的小數位數以及正確定位貨幣符號。例如。 double值2.4將返回es_ES語言環境的「2,40€」和jp_JP語言環境的「¥2」。

let formatter = NumberFormatter() 
formatter.locale = Locale.current // Change this to another locale if you want to force a specific locale, otherwise this is redundant as the current locale is the default already 
formatter.numberStyle = .currency 
if let formattedTipAmount = formatter.string(from: tipAmount as NSNumber) { 
    tipAmountLabel.text = "Tip Amount: \(formattedTipAmount)" 
} 
+0

僅供參考 - 無需將格式化程序的「locale」設置爲「Locale.current」,因爲這是默認設置。 – rmaddy

+2

是的,我知道,我添加了一條評論,說它是多餘的。想保持在那裏,以顯示它可以很容易地改變。 –

+0

工作得很好。 –

7

最好的辦法是創建一個NSNumberFormatter。 (Swift 3中的NumberFormatter)。您可以請求貨幣,它將設置字符串以遵循用戶的本地化設置,這很有用。

如果你想迫使美國格式的美元和美分字符串可以格式化這樣說:

let amount: Double = 123.45 

let amountString = String(format: "$%.02f", amount) 
-1

方法如下:

let currentLocale = Locale.current 
    let currencySymbol = currentLocale.currencySymbol 
    let outputString = "\(currencySymbol)\(String(format: "%.2f", totalBillAmount))" 

第一行:你獲取當前區域設置

第二行:您將獲得該語言環境的currencySymbol。 ($,£等)

第3行:使用格式初始化程序將您的Double截斷爲2位小數。

+0

不要這樣做。使用'NumberFormatter'。這種方法有很多問題,使用'NumberFormatter'很容易避免。 – rmaddy

6

除了被別人討論的NumberFormatterString(format:),你可能要考慮使用DecimalNSDecimalNumber和控制四捨五入自己,從而避免浮點運算的問題。如果你正在做一個簡單的小費計算器,那可能沒有必要。但是,如果你在做一些事情,比如在一天結束時添加提示,如果你沒有使用十進制數字進行數字整理和/或數學運算,那麼可以引入錯誤。

因此,繼續和配置格式化:

let formatter: NumberFormatter = { 
    let _formatter = NumberFormatter() 
    _formatter.numberStyle = .decimal 
    _formatter.minimumFractionDigits = 2 
    _formatter.maximumFractionDigits = 2 
    _formatter.generatesDecimalNumbers = true 
    return _formatter 
}() 

,然後,用十進制數:

let string = "2.03" 
let tipRate = Decimal(sign: .plus, exponent: -3, significand: 125) // 12.5% 
guard let billAmount = formatter.number(from: string) as? Decimal else { return } 
let tip = (billAmount * tipRate).rounded(2) 

guard let output = formatter.string(from: tip as NSDecimalNumber) else { return } 
print("\(output)") 

extension Decimal { 

    /// Round `Decimal` number to certain number of decimal places. 
    /// 
    /// - Parameters: 
    /// - scale: How many decimal places. 
    /// - roundingMode: How should number be rounded. Defaults to `.plain`. 
    /// - Returns: The new rounded number. 

    func rounded(_ scale: Int, roundingMode: RoundingMode = .plain) -> Decimal { 
     var value = self 
     var result: Decimal = 0 
     NSDecimalRound(&result, &value, scale, roundingMode) 
     return result 
    } 
} 

很明顯,你可以取代上述所有「2位小數」引用任何數字都適合您使用的貨幣(或可能是我們e爲小數位數的變量)。

+0

爲什麼不使用'NumberFormatter'的貨幣風格?並非所有貨幣都使用2位小數。 – rmaddy

+1

是的,你可以做到這一點。而且,您甚至可以查找您應該舍入的小數位數。無可否認,使用'.currency'引入了其他問題(例如,字符串的解析變得很隨意;它假定你不是旅行和處理其他貨幣等)。根據應用程序的不同,有時用戶可以更輕鬆地指定小數位並完成它。此外,我的觀點並非格式化,而是避免浮點數學與貨幣的總法律顧問。 – Rob

+0

四捨五入問題的另一種方法是將「美元和美分」(或歐元,或謝克爾或其他)數量乘以100(或整個單位中的小數單位數,對於沒有100美分的貨幣)。然後使用整數數學,並手動格式化輸出以插入小數分隔符。該方法還可以避免浮點錯誤。 –