可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I'm new to Swift programming and I've been creating a simple tip calculator app in Xcode 8.2, I have my calculations set up within my IBAction
below. But when I actually run my app and input an amount to calculate (such as 23.45), it comes up with more than 2 decimal places. How do I format it to .currency
in this case?
@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)"
}
}
回答1:
You can use this string initializer if you want to force the currency to $:
String(format: "Tip Amount: $%.02f", tipAmount)
If you want it to be fully dependent on the locale settings of the device, you should use a NumberFormatter
. This will take into account the number of decimal places for the currency as well as positioning the currency symbol correctly. E.g. the double value 2.4 will return "2,40 €" for the es_ES locale and "¥ 2" for the jp_JP locale.
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)"
}
回答2:
The best way to do this is to create an NSNumberFormatter
. (NumberFormatter
in Swift 3.) You can request currency and it will set up the string to follow the user's localization settings, which is useful.
If you want to force a US-formatted dollars and cents string you can format it this way:
let amount: Double = 123.45
let amountString = String(format: "$%.02f", amount)
回答3:
In addition to the NumberFormatter
or String(format:)
discussed by others, you might want to consider using Decimal
or NSDecimalNumber
and control the rounding yourself, thereby avoid floating point issues. If you're doing a simple tip calculator, that probably isn't necessary. But if you're doing something like adding up the tips at the end of the day, if you don't round the numbers and/or do your math using decimal numbers, you can introduce errors.
So, go ahead and configure your formatter:
let formatter: NumberFormatter = {
let _formatter = NumberFormatter()
_formatter.numberStyle = .decimal
_formatter.minimumFractionDigits = 2
_formatter.maximumFractionDigits = 2
_formatter.generatesDecimalNumbers = true
return _formatter
}()
and then, use decimal numbers:
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)")
Where
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
}
}
Obviously, you can replace all the above "2 decimal place" references with whatever number is appropriate for the currency you are using (or possibly use a variable for the number of decimal places).
回答4:
How to do it in Swift 4:
let myDouble = 9999.99
let currencyFormatter = NumberFormatter()
currencyFormatter.usesGroupingSeparator = true
currencyFormatter.numberStyle = .currency
// localize to your grouping and decimal separator
currencyFormatter.locale = Locale.current
// We'll force unwrap with the !, if you've got defined data you may need more error checking
let priceString = currencyFormatter.string(from: NSNumber(value: myDouble))!
print(priceString) // Displays $9,999.99 in the US locale
回答5:
You can to convert like that: this func convert keep for you maximumFractionDigits whenever you want to do
static func df2so(_ price: Double) -> String{
let numberFormatter = NumberFormatter()
numberFormatter.groupingSeparator = ","
numberFormatter.groupingSize = 3
numberFormatter.usesGroupingSeparator = true
numberFormatter.decimalSeparator = "."
numberFormatter.numberStyle = .decimal
numberFormatter.maximumFractionDigits = 2
return numberFormatter.string(from: price as NSNumber)!
}
i create it in class Model
then when you call , you can accecpt it another class , like this
print("InitData: result convert string " + Model.df2so(1008977.72))
//InitData: result convert string "1,008,977.72"
回答6:
you can create an Extension for either string or Int, I would show an example with String
extension String{
func toCurrencyFormat() -> String {
if let intValue = Int(self){
let numberFormatter = NumberFormatter()
numberFormatter.locale = Locale(identifier: "ig_NG")/* Using Nigeria's Naira here, please change to your locale, link below to get all locale identifier.*/
numberFormatter.numberStyle = NumberFormatter.Style.currency
return numberFormatter.string(from: NSNumber(value: intValue)) ?? ""
}
return ""
}
}
link to get all locale identifier
回答7:
Here's how:
let currentLocale = Locale.current
let currencySymbol = currentLocale.currencySymbol
let outputString = "\(currencySymbol)\(String(format: "%.2f", totalBillAmount))"
1st line: You're getting the current locale
2nd line: You're getting the currencySymbol for that locale. ($, £, etc)
3rd line: Using the format initializer to truncate your Double to 2 decimal places.