2017-01-09 39 views
15

Ben Swift programlama için yeni ve Xcode 8.2'de basit bir uç hesap makinesi uygulaması oluşturuyorum, benim IBAction aşağıda benim hesaplamalar benim kurmak var. Ancak, uygulamanızı gerçekten çalıştırdığımda ve hesaplamak için bir miktar girdigimde (23,45 gibi), 2'den fazla ondalık basamakla gelir. Bu durumda .currency'a nasıl biçimlendiririm? Eğer $ para birimini zorlamak istiyorsanızNasıl bir Çift Para Birimi biçimlendirmek - 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)" 
    } 
} 

cevap

25

Bu dize başlatıcı kullanabilirsiniz:

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

Eğer cihazın yerel ayarlarına tamamen bağımlı olmasını istiyorsanız, bir kullanmalıdır NumberFormatter. Bu, para birimi için ondalık basamakların sayısını ve para birimi sembolünü doğru bir şekilde konumlandırmayı dikkate alacaktır. Örneğin. çift ​​değer 2.4, es_ES yerel ayarı için "2,40 €" ve jp_JP yerel ayarı için "¥ 2" değerini döndürecektir.

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

FYI - biçimlendiricinin 'yerel ayarını 'Locale.current' olarak ayarlamaya gerek yoktur çünkü bu varsayılan değerdir. – rmaddy

+2

Evet, biliyorum, gereksiz olduğunu söylemek için bir yorum ekledim. Kolayca değiştirilebileceğini göstermek için orada tutmak istedim. –

+0

Çok iyi çalıştım. –

7

Bunu yapmanın en iyi yolu, bir NSNumberFormatter oluşturmaktır. (NumberFormatter Swift 3'teki) Para birimini isteyebilir ve dizeyi, kullanıcının yerelleştirme ayarlarına uygun olarak ayarlayacaktır, bu da yararlıdır.

bir ABD biçimlendirilmiş dolar ve sent dize zorlamak istiyorsanız bu şekilde biçimlendirebilirsiniz:

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

1 satır:: Sen akımı alıyoruz

İşte
let amount: Double = 123.45 

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

nasıl locale

2. satır: Bu yerele için para birimi simgesini alıyorsunuz. ($, £, vb)

3. satır: Çift ile 2 ondalık basamağını kesmek için biçimlendirici biçimlendiricisini kullanarak. Başkaları tarafından tartışılan NumberFormatter veya String(format:) ek olarak

+0

Bunu yapmayın. 'NumberFormatter 'öğesini kullanın. Bu yaklaşım 'NumberFormatter 'kullanılarak kolayca önlenebilen birçok probleme sahiptir. – rmaddy

6

, böylelikle nokta sorunlarını kayan önlemek, Decimal veya NSDecimalNumber kullanmayı düşünün ve kendinizi yuvarlama kontrol etmek isteyebilirsiniz. Basit bir uç hesap makinesi yapıyorsanız, muhtemelen gerekli değildir. Ancak, günün sonunda ipuçlarını eklemek gibi bir şey yapıyorsanız, sayıları çevirmiyorsanız ve/veya ondalık sayıları kullanarak matematiğinizi yapıyorsanız, hatalar yapabilirsiniz.

Yani, devam edin ve biçimlendirici yapılandırmak: Nerede

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 
    } 
} 

Açıkçası, her şeyden yerini alabilir

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)") 

:

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

ardından, ondalık sayılar kullanmak Kullandığınız para birimine (veya muhtemelen bize) uygun olan sayı ile "2 ondalık basamak" referansı e ondalık basamak sayısı için bir değişken).

+0

Neden "NumberFormatter" için para birimi stilini kullanmıyorsunuz? Tüm para birimleri 2 ondalık basamak kullanmaz. – rmaddy

+1

Evet, bunu yapabilirsin. Ve sonra, yuvarlamanız gereken ondalık basamakların sayısını bile arayabilirsiniz. Kuşkusuz, '.currency' kullanılarak başka sorunlar ortaya çıkar (örneğin dizelerin ayrıştırılması anlaşılır hale gelir; seyahat etmediğinizi ve başka bir para birimi ile uğraştığınızı varsayar). Uygulamaya bağlı olarak, bazen kullanıcının ondalık basamakları belirtmesine ve bununla birlikte bitmesine izin vermek daha kolaydır. Ayrıca, benim nokta biçimlendirici değildi, aksine para birimleri ile kayan nokta matematik önlemek için genel bir danışman değildi. – Rob

+0

Yuvarlama sorununa başka bir yaklaşım da, 100 sente sahip olmayan para birimleri için "dolar ve sent" (veya avro veya şekel veya herhangi bir miktar) miktarını 100 (veya tüm birimdeki kesirli birimlerin sayısı ile çarpmaktır)). Sonra tamsayı matematik kullanın ve ondalık ayırıcı eklemek için çıkışı elle biçimlendirin. Bu yaklaşım aynı zamanda kayan nokta hatalarını da önler. –