Çift değeri hızlıca x ondalık basamak sayısına yuvarlama


395

Swift'te bir çift değerin x ondalık basamağa nasıl yuvarlanacağını söyleyen var mı?

Sahibim:

var totalWorkTimeInHours = (totalWorkTime/60/60)

İle totalWorkTimeikinci bir NSTimeInterval (çift) olması.

totalWorkTimeInHours Bana saatleri verecek, ama bu kadar uzun bir sayıdaki zaman miktarını veriyor, örneğin 1.543240952039 ...

Yazdırdığımda bunu nasıl 1.543'e yuvarlayabilirim totalWorkTimeInHours?


1
Bkz Cevabımı çift kullanarak Darwin'i yuvarlamak en fazla 9 farklı yollar bulmak round(_:), Double round(), NSStringbaşlatıcı, Stringbaşlatıcı, NumberFormatterÇift uzantısı hatta NSDecimalNumberve Decimal.
Imanou Petit

@Rounded, hızlı bir 5.1 mülk sarmalayıcısı: gist.github.com/abhijithpp/1cc41b41a5d1c8f007da90f20bc0c65f
Abhijith

Yanıtlar:


389

Bunu yapmak için Swift roundişlevini kullanabilirsiniz.

A'yı Double3 basamaklı bir hassasiyetle yuvarlamak için , önce 1000 ile çarpın, yuvarlayın ve yuvarlanmış sonucu 1000'e bölün:

let x = 1.23556789
let y = Double(round(1000*x)/1000)
print(y)  // 1.236

Her türlü çözüm printf(...)veya String(format: ...)çözüm dışında, bu işlemin sonucu hala türdedir Double.

DÜZENLEME:
Bazen işe yaramadığı yorumlarıyla ilgili olarak, lütfen bunu okuyun:

Her Programcının Kayan Nokta Aritmetiği Hakkında Bilmesi Gerekenler


Bazı nedenlerle yardımcı olmaz .. Bunu aşağıdaki durumda kullanıyorum TransformOf <Double, String> (fromJSON: {Double (round (($ 0! NSString olarak .doubleValue * 100) / 100)}, toJSON: {"(0 $)"})
Fawkes

29
Oyun alanında benim için çalışmıyor: let rate = 9.94999999999; Double(round(rate * 100) / 100);Çıktı: 9.94999999999, 9.949999999999999Yalnızca baskı için çalışıyor, ancak değişkene nasıl atayabilirim?
Alexander Yakovlev

Bunun için Decimal kullanmalısınız, düz Çiftler değil.
csotiriou

13
"Her Bilgisayar Bilimcisinin Kayan Nokta Aritmetiği Hakkında Bilmesi Gerekenler" 73 sayfadır. TL nedir; DR? :)
JaredH

1
@HardikDG Hatırlamıyorum, üzgünüm :-)
Alexander Yakovlev

431

Swift 2 için uzantı

Daha genel bir çözüm, Swift 2 ve iOS 9 ile çalışan aşağıdaki uzantıdır:

extension Double {
    /// Rounds the double to decimal places value
    func roundToPlaces(places:Int) -> Double {
        let divisor = pow(10.0, Double(places))
        return round(self * divisor) / divisor
    }
}


Swift 3 için uzantı

Swift 3 roundyerine rounded:

extension Double {
    /// Rounds the double to decimal places value
    func rounded(toPlaces places:Int) -> Double {
        let divisor = pow(10.0, Double(places))
        return (self * divisor).rounded() / divisor
    }
}


Çift yuvarlatılmış 4 ondalık basamağa dönen örnek:

let x = Double(0.123456789).roundToPlaces(4)  // x becomes 0.1235 under Swift 2
let x = Double(0.123456789).rounded(toPlaces: 4)  // Swift 3 version

17
Swift's Double'in doğası, kesin olmayabilir - ikili olarak saklandığı / erişildiği için, bu yuvarlama işlevini kullansanız bile 3 ondalık basamağa yuvarlanmış bir sayı döndürmez: örneğin, round(8.46 * pow(10.0, 3.0)) / pow(10.0, 3.0)döndürür 8.460000000000001. Aynısını Float ile yapmak, en azından bu senaryoda , aslında işe yarıyor gibi görünüyor: round(Float(8.46) * pow(10.0, 3.0)) / pow(10.0, 3.0)verimler 8.46. Sadece kayda değer bir şey.
Ben Saufley

2
Ne yazık ki, bu artık Swift 3'te çalışmıyor, bu hatayı alıyorumNo '*' candidates produce the expected contextual result type 'FloatingPointRoundingRule'
koen

2
Çözümü güncelledim ve Swift 3 için bir uzantı ekledim
Sebastian

2
Daha hızlı olmak için 3 ... yuvarlak yuvarlatılmış olarak değiştirmelisiniz (Yerlere: Int) -> Çift
FouZ

2
@BenSaufley Ancak 98,68 girerseniz de çalışmaz. Bu durumda, 98.6800003
Alexander Khitev

340

Nasıl 1.543, diyelim ki, bu aşağı yuvarlamak yok ben yazdırırken totalWorkTimeInHours ?

totalWorkTimeInHoursYazdırma için 3 basamağa yuvarlamak için, dize Stringalan formatyapıcıyı kullanın:

print(String(format: "%.3f", totalWorkTimeInHours))

24
Yuvarlama değil, bu bir kesme
Eyeball

33
@Eyeball: Aslında yuvarlak. İstenen rakamlara yuvarlanan C printf işlevselliğiyle aynı davranıştır. Yani String(format: "%.3f", 1.23489)yazdırır1.235
zisoft

6
Orijinal poster, görüntülenecek bir dize değil, kullanılacak sayısal bir değer arıyor.
pr1001

17
@ pr1001, belki de öyle, ama o zaman net değildi ve 46 kişi cevabımı yararlı buldu. Yığın Taşması OP'ye yardım etmekten daha fazlasıdır.
vacawama

3
garip, bu her seferinde 0.00 döndürüyor.
Eric H

254

Swift 5 ile ihtiyaçlarınıza göre yuvarlatılmış bir sonuç elde etmek için aşağıdaki 9 stilden birini seçebilirsiniz Double.


# 1. FloatingPoint rounded()Yöntemi kullanarak

En basit durumda, Double rounded()yöntemi kullanabilirsiniz .

let roundedValue1 = (0.6844 * 1000).rounded() / 1000
let roundedValue2 = (0.6849 * 1000).rounded() / 1000
print(roundedValue1) // returns 0.684
print(roundedValue2) // returns 0.685

# 2. FloatingPoint rounded(_:)Yöntemi kullanarak

let roundedValue1 = (0.6844 * 1000).rounded(.toNearestOrEven) / 1000
let roundedValue2 = (0.6849 * 1000).rounded(.toNearestOrEven) / 1000
print(roundedValue1) // returns 0.684
print(roundedValue2) // returns 0.685

3.. Darwin roundfonksiyonunu kullanma

Vakıf, roundDarwin aracılığıyla bir işlev sunar .

import Foundation

let roundedValue1 = round(0.6844 * 1000) / 1000
let roundedValue2 = round(0.6849 * 1000) / 1000
print(roundedValue1) // returns 0.684
print(roundedValue2) // returns 0.685

4.. DoubleDarwin roundve powfonksiyonları ile oluşturulmuş özel bir uzatma yöntemi kullanmak

Önceki işlemi birçok kez tekrarlamak isterseniz, kodunuzu yeniden düzenlemek iyi bir fikir olabilir.

import Foundation

extension Double {
    func roundToDecimal(_ fractionDigits: Int) -> Double {
        let multiplier = pow(10, Double(fractionDigits))
        return Darwin.round(self * multiplier) / multiplier
    }
}

let roundedValue1 = 0.6844.roundToDecimal(3)
let roundedValue2 = 0.6849.roundToDecimal(3)
print(roundedValue1) // returns 0.684
print(roundedValue2) // returns 0.685

5.. NSDecimalNumber rounding(accordingToBehavior:)Yöntemi kullanarak

Gerekirse, NSDecimalNumberondalık sayıları yuvarlamak için ayrıntılı ancak güçlü bir çözüm sunar.

import Foundation

let scale: Int16 = 3

let behavior = NSDecimalNumberHandler(roundingMode: .plain, scale: scale, raiseOnExactness: false, raiseOnOverflow: false, raiseOnUnderflow: false, raiseOnDivideByZero: true)

let roundedValue1 = NSDecimalNumber(value: 0.6844).rounding(accordingToBehavior: behavior)
let roundedValue2 = NSDecimalNumber(value: 0.6849).rounding(accordingToBehavior: behavior)

print(roundedValue1) // returns 0.684
print(roundedValue2) // returns 0.685

6.. NSDecimalRound(_:_:_:_:)Fonksiyonu kullanarak

import Foundation

let scale = 3

var value1 = Decimal(0.6844)
var value2 = Decimal(0.6849)

var roundedValue1 = Decimal()
var roundedValue2 = Decimal()

NSDecimalRound(&roundedValue1, &value1, scale, NSDecimalNumber.RoundingMode.plain)
NSDecimalRound(&roundedValue2, &value2, scale, NSDecimalNumber.RoundingMode.plain)

print(roundedValue1) // returns 0.684
print(roundedValue2) // returns 0.685

7.. NSString init(format:arguments:)Başlatıcı kullanma

NSStringYuvarlama işleminizden bir geri dönmek istiyorsanız , NSStringbaşlatıcı kullanmak basit ama etkili bir çözümdür.

import Foundation

let roundedValue1 = NSString(format: "%.3f", 0.6844)
let roundedValue2 = NSString(format: "%.3f", 0.6849)
print(roundedValue1) // prints 0.684
print(roundedValue2) // prints 0.685

8.. String init(format:_:)Başlatıcı kullanma

Swift'in Stringtürü Vakıf'ın NSStringsınıfıyla doludur . Bu nedenle, Stringyuvarlama işleminizden bir geri dönmek için aşağıdaki kodu kullanabilirsiniz :

import Foundation

let roundedValue1 = String(format: "%.3f", 0.6844)
let roundedValue2 = String(format: "%.3f", 0.6849)
print(roundedValue1) // prints 0.684
print(roundedValue2) // prints 0.685

9.. kullanmaNumberFormatter

String?Yuvarlama işleminizden bir almayı bekliyorsanız , NumberFormatterson derece özelleştirilebilir bir çözüm sunar.

import Foundation

let formatter = NumberFormatter()
formatter.numberStyle = NumberFormatter.Style.decimal
formatter.roundingMode = NumberFormatter.RoundingMode.halfUp
formatter.maximumFractionDigits = 3

let roundedValue1 = formatter.string(from: 0.6844)
let roundedValue2 = formatter.string(from: 0.6849)
print(String(describing: roundedValue1)) // prints Optional("0.684")
print(String(describing: roundedValue2)) // prints Optional("0.685")

1
Mükemmel cevap. Ben Decimalücretsiz # köprülenmiş olan, # 5 kullanmayı düşünebilirsiniz önerebilir NSDecimalNumber. Decimalgibi yerli operatörler için Swift'in doğal tipi ve teklifler daha şık destektir +, -vb
Rob

@Rob Cevabımı işlevle güncelledim NSDecimalRound(_:_:_:_:). Teşekkürler.
Imanou Petit

# 9 seçeneğini kullanarak sabit kesir (hassas basamak sayısı) beklediğinizi garanti edersiniz, ondalık sayı 43.12345 ve kesir = 6 diyelim, 43.123450
Almas Adilbek

1
@ImanouPetit Bunu gönderdiğiniz için teşekkür ederiz. Birkaç uzantıyı nuke edebilirim.
Adrian

Üzgünüm NumberFormatterson seçenek kullanıcılara sayı sunarken ilk seçenek olsa. Başka hiçbir yöntem uygun şekilde yerelleştirilmiş sayılar üretmez.
Sulthan

93

Swift 2.0 ve Xcode 7.2'de:

let pi: Double = 3.14159265358979
String(format:"%.2f", pi)

Misal:

resim açıklamasını buraya girin


50

Bu tamamen çalışan bir kod

Swift 3.0 / 4.0 / 5.0, Xcode 9.0 GM / 9.2 ve üstü

let doubleValue : Double = 123.32565254455
self.lblValue.text = String(format:"%.f", doubleValue)
print(self.lblValue.text)

çıktı - 123

let doubleValue : Double = 123.32565254455
self.lblValue_1.text = String(format:"%.1f", doubleValue)
print(self.lblValue_1.text)

çıktı - 123.3

let doubleValue : Double = 123.32565254455
self.lblValue_2.text = String(format:"%.2f", doubleValue)
print(self.lblValue_2.text)

çıktı - 123.33

let doubleValue : Double = 123.32565254455
self.lblValue_3.text = String(format:"%.3f", doubleValue)
print(self.lblValue_3.text)

çıktı - 123.326


1
bir satır ?, 3 satır gibi görünüyor;)
Petter Friberg

dizeleri kullanarak bir şeyleri hesaplayamazsınız, bunun doğru bir cevap olduğunu düşünmüyorum çünkü sadece görüntülemek için.
JBarros35

25

Yogi'nin cevabına dayanarak, işi yapan bir Swift işlevi:

func roundToPlaces(value:Double, places:Int) -> Double {
    let divisor = pow(10.0, Double(places))
    return round(value * divisor) / divisor
}

20

Swift 3.0 ve Xcode 8.0'da:

extension Double {
    func roundTo(places: Int) -> Double {
        let divisor = pow(10.0, Double(places))
        return (self * divisor).rounded() / divisor
    }
}

Bu uzantıyı şu şekilde kullanın:

let doubleValue = 3.567
let roundedValue = doubleValue.roundTo(places: 2)
print(roundedValue) // prints 3.56

19

Swift 4, Xcode 10

yourLabel.text =  String(format:"%.2f", yourDecimalValue)

1
Ben downvote vermedim, ama bunun nedeni sayının değil, bir sayının dize temsilini döndürüyor nedeni olduğunu düşünüyorum. İhtiyacınız olan tek şey budur, ancak daha fazla kullanım için sayının kendisinin yuvarlanmasını isteyebilirsiniz. OP "bastığımda" dedi, bu yüzden bu durumda kabul edilebilir, kolay ve temiz bir çözüm olduğunu düşünüyorum.
Ben Stahl

1
Mükemmel. Tek hat çözümü. Yalnızca ondalık değerleri etiketlerimde Dizeler olarak göstermem gerekiyordu.
Zeeshan

18

Ondalık basamaklardan sonraki belirli basamakların kodu:

var a = 1.543240952039
var roundedString = String(format: "%.3f", a)

Burada% .3f, bu sayıya 3 ondalık basamağa yuvarlatılmasını söyler. Ve çift sayı istiyorsanız, bu kodu kullanabilirsiniz:

// Çifte Dize

var roundedString = Double(String(format: "%.3f", b))


14

Dahili Foundation Darwin kütüphanesini kullanın

SWIFT 3

extension Double {
    func round(to places: Int) -> Double {
        let divisor = pow(10.0, Double(places))
        return Darwin.round(self * divisor) / divisor
    }
}

Kullanımı:

let number:Double = 12.987654321
print(number.round(to: 3)) 

Çıktılar: 12.988


9

Kullanışlı bir yol, Çift tip uzatma kullanımı olabilir

extension Double {
    var roundTo2f: Double {return Double(round(100 *self)/100)  }
    var roundTo3f: Double {return Double(round(1000*self)/1000) }
}

Kullanımı:

let regularPie:  Double = 3.14159
var smallerPie:  Double = regularPie.roundTo3f  // results 3.142
var smallestPie: Double = regularPie.roundTo2f  // results 3.14

9

DoubleDeğerleri yuvarlamak istiyorsanız, Swift'i kullanmak isteyebilirsiniz, Decimalböylece bu yuvarlanmış değerlerle matematik yapmaya çalışırken ortaya çıkabilecek herhangi bir hata ortaya çıkarmazsınız. Eğer kullanırsanız Decimal, doğru o yuvarlak kayan nokta değeri ondalık değerleri temsil edebilir.

Böylece şunları yapabilirsiniz:

extension Double {
    /// Convert `Double` to `Decimal`, rounding it to `scale` decimal places.
    ///
    /// - Parameters:
    ///   - scale: How many decimal places to round to. Defaults to `0`.
    ///   - mode:  The preferred rounding mode. Defaults to `.plain`.
    /// - Returns: The rounded `Decimal` value.

    func roundedDecimal(to scale: Int = 0, mode: NSDecimalNumber.RoundingMode = .plain) -> Decimal {
        var decimalValue = Decimal(self)
        var result = Decimal()
        NSDecimalRound(&result, &decimalValue, scale, mode)
        return result
    }
}

Ardından, yuvarlatılmış Decimaldeğeri şöyle elde edebilirsiniz :

let foo = 427.3000000002
let value = foo.roundedDecimal(to: 2) // results in 427.30

Ayrıca, belirtilen sayıda ondalık basamakla görüntülemek (kullanıcının geçerli yerel ayarı için dizeyi yerelleştirmenin yanı sıra), aşağıdakileri kullanabilirsiniz NumberFormatter:

let formatter = NumberFormatter()
formatter.maximumFractionDigits = 2
formatter.minimumFractionDigits = 2

if let string = formatter.string(for: value) {
    print(string)
}

2
Şimdiye kadarki en iyi cevap.
Codetard

(4.81).roundedDecimal(to: 2, mode: .down)4.81 yerine 4.8 döndürecek, Decimal(string: self.description)!kesin olarak kullanacakdecimalValue
vk.edward.li

1
@ vk.edward.li - Evet, ondalık sayıları yukarı / aşağı yuvarlama konusunda dikkatli olunmalıdır, çünkü 4.81 gibi değerler doğru bir şekilde temsil edilemez Double(olur 4.8099999999999996). Ama kullanmaya karşı öneriyorum description( kullandığı yuvarlama belgelenmemiş ve değişebilir). Gerçekten ondalık doğrulukta matematik yapmak istiyorsanız, Doubletamamen kaçınmalısınız ve bunun yerine Decimaldoğrudan kullanmalısınız (örn. Decimal(sign: .plus, exponent: -2, significand: 481)Veya Decimal(string: "4.81"). Ama kullanmayın description.
Rob

@Rob genellikle Double olarak saklanırsa "4.81" dize değerini elde etmek imkansızdır, bu nedenle zaten kaybolmuş hassasiyeti düzeltmek için self.description (modifiye edilmiş Grisu2 algoritması) kullanmanız gerekir
vk.edward.li

Ne demek istediğini anlıyorum. Ben sadece sizin çözümünüze katılmıyorum. descriptionYöntemin yuvarlama davranışı ne belgelenmiştir ne de garanti edilmemektedir. Ayrıca, yerelleştirilmemiştir. IMHO, descriptiongiriş amaçları dışında herhangi bir şey için bir hata . Tamamen kullanmaktan Decimalkaçınarak Doubleya da sadece farklı bir yuvarlama modu kullanırım. Gerekirse, Grisu tarzı algoritma kullanan kendi yerelleştirilmiş yönteminizi kullanın (ancak kaç ondalık basamak yuvarlamak istediğinizi bildiğinizde gereksiz görünüyor). Ama ben bu yardımcı davranışına güvenmekten kaçınırım description.
Rob

8

Bu, ihtiyaçlarınız biraz daha karmaşıksa kullanışlı olabilecek uzun bir geçici çözümdür. Swift'de bir sayı biçimlendirici kullanabilirsiniz.

let numberFormatter: NSNumberFormatter = {
    let nf = NSNumberFormatter()
    nf.numberStyle = .DecimalStyle
    nf.minimumFractionDigits = 0
    nf.maximumFractionDigits = 1
    return nf
}()

Diyelim ki yazdırmak istediğiniz değişkeniniz

var printVar = 3.567

Bu, istenen biçimde döndürüldüğünden emin olacaktır:

numberFormatter.StringFromNumber(printVar)

Dolayısıyla buradaki sonuç "3.6" (yuvarlatılmış) olacaktır. Bu en ekonomik çözüm olmasa da, OP'den yazdırma (bu durumda bir String istenmeyen bir durum olmadığı) ve bu sınıfın birden fazla parametrenin ayarlanmasına izin verdiği için veriyorum.


1
Herhangi bir formatlayıcının programlı olarak oldukça pahalı olduğunu hızlı bir şekilde not edin, bu da hızlı veya tekrarlı olarak yapılması gereken görevler için kötü tavsiye edilir.
Jonathan Thornton

7

Kullanmak istiyorum

print(String(format: "%.3f", totalWorkTimeInHours))

ve .3f değerini istediğiniz sayıda ondalık sayı olarak değiştirin


NSTimeInterval'a girmemek için 3 basamaklı basmak istedi
Mohsen Hossein

7

Ya:

  1. Kullanma String(format:):

    • Typecast Doubleiçin Stringbirlikte %.3fo zamanlar biçim belirteci veDouble

      Double(String(format: "%.3f", 10.123546789))!
    • Veya DoubleN-Ondalık basamakları işlemek için genişletin :

      extension Double {
          func rounded(toDecimalPlaces n: Int) -> Double {
              return Double(String(format: "%.\(n)f", self))!
          }
      }
  2. Hesaplamaya göre

    • 10 ^ 3 ile çarpın, yuvarlayın ve sonra 10 ^ 3'e bölün ...

      (1000 * 10.123546789).rounded()/1000
    • Veya DoubleN-Ondalık basamakları işlemek için genişletin :

      extension Double {    
          func rounded(toDecimalPlaces n: Int) -> Double {
              let multiplier = pow(10, Double(n))
              return (multiplier * self).rounded()/multiplier
          }
      }

6

Bu, N anlamlı basamağa yuvarlamanın daha esnek bir algoritmasıdır

Swift 3 çözümü

extension Double {
// Rounds the double to 'places' significant digits
  func roundTo(places:Int) -> Double {
    guard self != 0.0 else {
        return 0
    }
    let divisor = pow(10.0, Double(places) - ceil(log10(fabs(self))))
    return (self * divisor).rounded() / divisor
  }
}


// Double(0.123456789).roundTo(places: 2) = 0.12
// Double(1.23456789).roundTo(places: 2) = 1.2
// Double(1234.56789).roundTo(places: 2) = 1200

6

Bir double özelliğini biçimlendirmenin en iyi yolu, Apple'ın önceden tanımlanmış yöntemlerini kullanmaktır.

mutating func round(_ rule: FloatingPointRoundingRule)

FloatingPointRoundingRule aşağıdaki olasılıklara sahip bir numaralandırmadır

Numaralandırma Vakaları:

Büyüklüğü kaynağınkinden büyük veya ona eşit olan en yakın değere yuvarlayın .

case down Kaynağa eşit veya daha küçük olan, izin verilen en yakın değere yuvarlayın.

caseNearestOrAwayFromZero için izin verilen en yakın değere yuvarlayın ; iki değer eşit derecede yakınsa, daha büyük büyüklüğe sahip olan seçilir.

İzin verilen en yakın değere yuvarlayın ; iki değer eşit derecede yakınsa, çift değer seçilir.

Zero: Büyüklüğü kaynağınkinden küçük veya ona eşit olan en yakın değere yuvarlayın .

case up Kaynaktan büyük veya ona eşit olan en yakın değere yuvarlayın.

var aNumber : Double = 5.2
aNumber.rounded(.up) // 6.0

6

çift ​​değeri x ondalık
NO sayısına yuvarlayın . ondalık basamaktan sonraki basamak sayısı

var x = 1.5657676754
var y = (x*10000).rounded()/10000
print(y)  // 1.5658 

var x = 1.5657676754 
var y = (x*100).rounded()/100
print(y)  // 1.57 

var x = 1.5657676754
var y = (x*10).rounded()/10
print(y)  // 1.6

Bu koda ne oluyor? Bu üç örnek ne gösteriyor?
rene

Yalnızca kod yanıtları yardımcı olmaz, lütfen bu örneklerin her birinin ne yaptığını açıklamaya çalışın.
Moe

5

Swift değil ama eminim fikri anladın.

pow10np = pow(10,num_places);
val = round(val*pow10np) / pow10np;

4

Bu Swift 5'te çalışıyor gibi görünüyor.

Bunun için standart bir fonksiyonun bulunmaması oldukça şaşırmıştı.

// Yuvarlama ile Çift-n-ondalık basamakların kesilmesi

extension Double {

    func truncate(to places: Int) -> Double {
    return Double(Int((pow(10, Double(places)) * self).rounded())) / pow(10, Double(places))
    }

}

2

Bu uzantıyı ekleyebilirsiniz:

extension Double {
    var clean: String {
        return self.truncatingRemainder(dividingBy: 1) == 0 ? String(format: "%.0f", self) : String(format: "%.2f", self)
    }
}

ve şöyle deyin:

let ex: Double = 10.123546789
print(ex.clean) // 10.12

Bu bir dize olarak temsil düzgün bir uygulamasıdır. Hala çift olarak koruduktan sonra rakam temsili sayısının bir uzantısı yazmanın mümkün veya rasyonel olup olmadığını merak ediyorum.
thinkswift

2

Kayan nokta hatalarını önlemek için Ondalık kullanın

extension Float {
    func rounded(rule: NSDecimalNumber.RoundingMode, scale: Int) -> Float {
        var result: Decimal = 0
        var decimalSelf = NSNumber(value: self).decimalValue
        NSDecimalRound(&result, &decimalSelf, scale, rule)
        return (result as NSNumber).floatValue
    }
}

ex.
Ölçek: 2 ve .down ile Float kullanılırken 1075.58, 1075.57'ye yuvarlar: Ölçek: 2 ve .down
ile Ondalık kullanılırken 1075.58, 1075.58'e yuvarlar


1

Bir kullanıcının girdisini düzeltmenin mümkün olup olmadığını merak ettim. Bir dolar tutarı için iki yerine üç ondalık sayı girerse. 1.11 yerine 1.111 deyin, yuvarlayarak düzeltebilir misiniz? Birçok nedenden dolayı cevap hayır! Para ile yani 0.001 üzerinde bir şey sonunda gerçek bir çek defterinde sorunlara neden olacaktır.

Noktadan sonra kullanıcıların girişini çok fazla değer için kontrol eden bir işlev. Ama bu 1., 1.1 ve 1.11'e izin verecek.

Bir Dizeden Çifte başarılı dönüşüm için değerin önceden kontrol edildiği varsayılmaktadır.

//func need to be where transactionAmount.text is in scope

func checkDoublesForOnlyTwoDecimalsOrLess()->Bool{


    var theTransactionCharacterMinusThree: Character = "A"
    var theTransactionCharacterMinusTwo: Character = "A"
    var theTransactionCharacterMinusOne: Character = "A"

    var result = false

    var periodCharacter:Character = "."


    var myCopyString = transactionAmount.text!

    if myCopyString.containsString(".") {

         if( myCopyString.characters.count >= 3){
                        theTransactionCharacterMinusThree = myCopyString[myCopyString.endIndex.advancedBy(-3)]
         }

        if( myCopyString.characters.count >= 2){
            theTransactionCharacterMinusTwo = myCopyString[myCopyString.endIndex.advancedBy(-2)]
        }

        if( myCopyString.characters.count > 1){
            theTransactionCharacterMinusOne = myCopyString[myCopyString.endIndex.advancedBy(-1)]
        }


          if  theTransactionCharacterMinusThree  == periodCharacter {

                            result = true
          }


        if theTransactionCharacterMinusTwo == periodCharacter {

            result = true
        }



        if theTransactionCharacterMinusOne == periodCharacter {

            result = true
        }

    }else {

        //if there is no period and it is a valid double it is good          
        result = true

    }

    return result


}

1
//find the distance between two points
let coordinateSource = CLLocation(latitude: 30.7717625, longitude:76.5741449 )
let coordinateDestination = CLLocation(latitude: 29.9810859, longitude: 76.5663599)
let distanceInMeters = coordinateSource.distance(from: coordinateDestination)
let valueInKms = distanceInMeters/1000
let preciseValueUptoThreeDigit = Double(round(1000*valueInKms)/1000)
self.lblTotalDistance.text = "Distance is : \(preciseValueUptoThreeDigit) kms"

1
extension String{
  var roundedValue:String {
     return String(format: "%.3f", self)
}}

Kullanımı:

totalWorkTimeInHours.roundedValue

1

Sayı değerine sahip bir Metin öğesine ihtiyacınız varsa, SwiftUI için bir tane.

struct RoundedDigitText : View {
    let digits : Int
    let number : Double

    var body : some View {
        Text(String(format: "%.\(digits)f", number))
    }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.