การปัดเศษค่าสองเท่าเป็นจำนวนทศนิยมสิบตำแหน่งอย่างรวดเร็ว


395

ทุกคนสามารถบอกวิธีการปัดค่าสองเท่าเป็นจำนวนทศนิยมใน Swift ได้หรือไม่

ฉันมี:

var totalWorkTimeInHours = (totalWorkTime/60/60)

ด้วยtotalWorkTimeการเป็น NSTimeInterval (สองครั้ง) เป็นวินาที

totalWorkTimeInHours จะให้เวลาฉัน แต่ให้เวลากับฉันในจำนวนที่แม่นยำเช่น 1.543240952039 ......

ฉันจะปัดเศษลงเพื่อบอกว่า 1.543 เมื่อฉันพิมพ์ได้totalWorkTimeInHoursอย่างไร


1
ดูคำตอบของฉันที่จะหาได้ถึง 9 วิธีการที่แตกต่างกันรอบสองโดยใช้ดาร์วินround(_:), Double round(), NSStringการเริ่มต้น, Stringการเริ่มต้น, NumberFormatterขยายคู่หรือแม้กระทั่งการและNSDecimalNumber Decimal
Imanou Petit

@Rounded, ตัวห่อคุณสมบัติ 5.1 ที่รวดเร็ว: gist.github.com/abhijithpp/1cc41b41a5d1c8f007da90f20bc0c65f
Abhijith

คำตอบ:


389

คุณสามารถใช้roundฟังก์ชันของ Swift เพื่อทำสิ่งนี้

ในการปัด a Doubleด้วยความแม่นยำ 3 หลักก่อนอื่นคูณด้วย 1,000 ปัดเศษและหารผลลัพธ์ที่ถูกปัดเศษด้วย 1,000:

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

อื่น ๆ กว่าชนิดของใด ๆprintf(...)หรือการแก้ปัญหาที่เป็นผลมาจากการดำเนินการนี้ยังคงเป็นประเภทString(format: ...)Double

แก้ไข:
เกี่ยวกับความคิดเห็นที่บางครั้งมันไม่ทำงานโปรดอ่านนี้:

สิ่งที่โปรแกรมเมอร์ทุกคนควรรู้เกี่ยวกับเลขคณิตทศนิยม


ด้วยเหตุผลบางอย่างมันไม่ได้ช่วย .. ฉันใช้มันในกรณีต่อไปนี้ TransformOf <Double, String> (fromJSON: {Double (round (($ 0! as NSString) .doubleValue * 100) / 100)) toJSON: {"($ 0)"})
Fawkes

29
ใช้งานไม่ได้สำหรับฉันในสนามเด็กเล่น: let rate = 9.94999999999; Double(round(rate * 100) / 100);เอาท์พุท: 9.94999999999, 9.949999999999999ใช้ได้กับงานพิมพ์เท่านั้น แต่ฉันจะกำหนดให้ตัวแปรได้อย่างไร
Alexander Yakovlev

คุณควรใช้ทศนิยมสำหรับสิ่งนี้ไม่ใช่คู่ผสมธรรมดา
csotiriou

13
"สิ่งที่นักวิทยาศาสตร์คอมพิวเตอร์ทุกคนควรรู้เกี่ยวกับเลขทศนิยมคือ 73 หน้า TL; DR คืออะไร :)
JaredH

1
@HardikDG ฉันจำไม่ได้ขอโทษ :-)
Alexander Yakovlev

431

ส่วนขยายสำหรับ Swift 2

โซลูชันทั่วไปเพิ่มเติมคือส่วนขยายต่อไปนี้ซึ่งทำงานกับ Swift 2 และ iOS 9:

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

ใน Swift 3 roundจะถูกแทนที่ด้วย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
    }
}


ตัวอย่างที่ส่งกลับค่า double round เป็นทศนิยม 4 ตำแหน่ง:

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
ธรรมชาติของสวิฟท์คู่ดูเหมือนจะเป็นไปได้ว่ามันอาจจะไม่แน่ชัด - เนื่องจากวิธีที่มันเก็บไว้ / เข้าถึงได้ในไบนารีแม้จะใช้ฟังก์ชันนี้ปัดเศษจะไม่กลับมาเป็นจำนวนปัดเศษให้เป็นทศนิยม 3 ตำแหน่ง: เช่นผลตอบแทนround(8.46 * pow(10.0, 3.0)) / pow(10.0, 3.0) 8.460000000000001ทำแบบเดียวกันกับ Float, อย่างน้อยในสถานการณ์นี้ไม่ในความเป็นจริงดูเหมือนจะทำงาน: อัตราผลตอบแทนround(Float(8.46) * pow(10.0, 3.0)) / pow(10.0, 3.0) 8.46สิ่งที่น่าสังเกต
Ben Saufley

2
น่าเสียดายที่นี่ไม่ทำงานใน Swift 3 อีกต่อไปฉันได้รับข้อผิดพลาดนี้No '*' candidates produce the expected contextual result type 'FloatingPointRoundingRule'
koen

2
ฉันอัปเดตโซลูชันและเพิ่มส่วนขยายสำหรับ Swift 3
เซบาสเตียน

2
เพื่อความรวดเร็วมากขึ้น 3 ... คุณควรเปลี่ยน func round (toPaces places: Int) -> Double
FouZ

2
@BenSaufley แต่ก็ใช้ไม่ได้ถ้าคุณป้อน 98.68 ในกรณีนี้ฉันได้ 98.6800003
Alexander Khitev

340

ฉันจะปัดเศษลงเพื่อบอกว่า 1.543 เมื่อฉันพิมพ์ได้ totalWorkTimeInHoursอย่างไร

ในการปัดเศษtotalWorkTimeInHoursตัวเลข 3 หลักสำหรับการพิมพ์ให้ใช้ตัวStringสร้างซึ่งใช้formatสตริง:

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

24
นั่นคือการปัดเศษไม่ใช่การปัดเศษ
ลูกตา

33
@Eyeball: จริง ๆ แล้วมันไม่ได้รอบ มันเป็นพฤติกรรมเช่นเดียวกับฟังก์ชั่น C printf ซึ่งปัดเศษเป็นตัวเลขที่ร้องขอ ดังนั้นString(format: "%.3f", 1.23489)พิมพ์1.235
zisoft

6
โปสเตอร์ต้นฉบับกำลังมองหาค่าตัวเลขที่จะใช้ไม่ใช่สตริงที่จะแสดง
pr1001

17
@ pr1001 อาจเป็นเช่นนั้น แต่นั่นก็ไม่ชัดเจนในขณะนั้นและอีก 46 คนพบว่าคำตอบของฉันมีประโยชน์ Stack Overflow เป็นมากกว่าการช่วยเหลือ OP
vacawama

3
คี่นี่จะคืน 0.00 ทุกครั้ง
Eric H

254

กับสวิฟท์ 5 ตามความต้องการของคุณคุณสามารถเลือกหนึ่งของรูปแบบต่อไปนี้ 9Doubleเพื่อให้มีผลกลมจาก


# 1 ใช้FloatingPoint rounded()วิธีการ

ในกรณีที่ง่ายที่สุดคุณอาจใช้Double rounded()วิธีนี้

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(_:)วิธีการ

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 การใช้roundฟังก์ชั่นดาร์วิน

มูลนิธิเสนอroundฟังก์ชั่นผ่านทางดาร์วิน

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 การใช้Doubleวิธีการที่กำหนดเองส่วนขยายที่สร้างด้วยดาร์วินroundและpowฟังก์ชั่น

หากคุณต้องการที่จะทำซ้ำการดำเนินการก่อนหน้านี้หลายครั้งการปรับรหัสของคุณใหม่อาจเป็นความคิดที่ดี

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:)วิธีการ

หากจำเป็นให้NSDecimalNumberบริการโซลูชัน verbose แต่ทรงพลังสำหรับการปัดเศษทศนิยม

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(_:_:_:_:)ฟังก์ชั่น

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:)initializer

หากคุณต้องการส่งคืน a NSStringจากการปัดเศษการใช้NSStringinitializer เป็นโซลูชันที่เรียบง่าย แต่มีประสิทธิภาพ

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:_:)initializer

Stringประเภทของสวิฟท์นั้นเชื่อมโยงกับNSStringชั้นเรียนของมูลนิธิ ดังนั้นคุณสามารถใช้รหัสต่อไปนี้เพื่อส่งคืนStringการดำเนินการปัดเศษของคุณ:

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 การใช้NumberFormatter

หากคุณคาดว่าจะได้รับString?จากการดำเนินการปัดเศษของคุณNumberFormatterนำเสนอโซลูชั่นที่ปรับแต่งได้สูง

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
คำตอบที่ดี ผมอาจจะแนะนำใน # 5 ที่คุณอาจพิจารณาใช้ซึ่งเป็นโทรฟรีไปยังสะพานDecimal เป็นประเภทพื้นเมืองสวิฟท์และข้อเสนอการสนับสนุนสง่างามมากขึ้นสำหรับผู้ประกอบการชาวพื้นเมืองเช่น, ฯลฯNSDecimalNumberDecimal+-
ร็อบ

@Rob ฉันได้อัพเดทคำตอบพร้อมNSDecimalRound(_:_:_:_:)ฟังก์ชั่นแล้ว ขอบคุณ
Imanou Petit

การใช้ตัวเลือก # 9 จะรับประกันได้ว่าคุณจะได้รับเศษส่วนคงที่ (จำนวนหลักความแม่นยำ) สมมติว่าเลขทศนิยม 43.12345 และเศษส่วน = 6 คุณจะได้รับ 43.123450
Almas Adilbek

1
@ImanouPetit ขอบคุณที่โพสต์ข้อความนี้ ฉันสามารถทำนามสกุลสองสามอย่างได้
Adrian

ฉันเศร้าNumberFormatterเป็นตัวเลือกสุดท้ายในขณะที่มันควรจะเป็นครั้งแรกสำหรับการนำเสนอตัวเลขให้กับผู้ใช้ ไม่มีวิธีอื่นใดที่สร้างหมายเลขที่แปลเป็นภาษาท้องถิ่นอย่างเหมาะสม
Sulthan


50

นี่เป็นรหัสที่ทำงานได้อย่างสมบูรณ์

Swift 3.0 / 4.0 / 5.0, Xcode 9.0 GM / 9.2 ขึ้นไป

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

เอาท์พุท - 123

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

เอาท์พุท - 123.3

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

เอาท์พุท - 123.33

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

เอาท์พุท - 123.326


1
บรรทัดเดียวดูเหมือนว่า 3 บรรทัด;)
Petter Friberg

คุณไม่สามารถคำนวณสิ่งต่าง ๆ โดยใช้สตริงได้ฉันไม่คิดว่ามันเป็นคำตอบที่ถูกต้องเพราะมันมีไว้สำหรับแสดงเท่านั้น
JBarros35

25

จากคำตอบของโยคีนี่คือฟังก์ชั่น Swift ที่ทำงาน:

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

20

ใน Swift 3.0 และ Xcode 8.0:

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

ใช้ส่วนขยายนี้เช่น:

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
ฉันไม่ได้ลงคะแนน แต่ฉันคิดว่าเหตุผลอาจเป็นเพราะนี่เป็นการส่งคืนสตริงแทนจำนวนไม่ใช่จำนวน ซึ่งเป็นสิ่งที่ดีถ้านั่นคือทั้งหมดที่คุณต้องการ แต่คุณอาจต้องการตัวเลขที่ปัดเศษออกเพื่อใช้งานต่อไป OP อธิบายว่า "เมื่อฉันพิมพ์" ดังนั้นฉันคิดว่านี่เป็นวิธีแก้ปัญหาที่ยอมรับได้ง่ายและสะอาดในกรณีนี้
Ben Stahl

1
สมบูรณ์ ทางออกเดียว ฉันต้องการแสดงค่าทศนิยมเป็น Strings ในป้ายกำกับของฉัน
zeeshan

18

รหัสสำหรับตัวเลขเฉพาะหลังจากทศนิยมคือ:

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

นี่คือ% .3f บอกให้ swift ทำให้ตัวเลขนี้ถูกปัดเศษเป็นทศนิยม 3 ตำแหน่งและหากคุณต้องการตัวเลขสองตัวคุณสามารถใช้รหัสนี้:

// String เป็น Double

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


14

ใช้ห้องสมุด Foundation Darwin ในตัว

สวิฟท์ 3

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

การใช้งาน:

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

เอาท์พุท: 12.988


9

วิธีที่สะดวกสามารถใช้เป็นนามสกุลDouble Type ได้

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

การใช้งาน:

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

9

หากคุณต้องการปัดเศษDoubleค่าคุณอาจต้องการใช้ Swift Decimalดังนั้นคุณจะไม่แนะนำข้อผิดพลาดใด ๆ ที่สามารถครอบตัดเมื่อพยายามคำนวณทางคณิตศาสตร์ด้วยค่าที่ปัดเศษเหล่านี้ หากคุณใช้Decimalจะสามารถแสดงค่าทศนิยมของค่าทศนิยมที่ปัดเศษ

ดังนั้นคุณสามารถทำได้:

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

จากนั้นคุณสามารถรับDecimalค่าที่ปัดเศษดังนี้:

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

และถ้าคุณต้องการที่จะแสดงมันด้วยจำนวนทศนิยมที่ระบุ (เช่นเดียวกับการแปลสตริงสำหรับสถานที่ปัจจุบันของผู้ใช้) คุณสามารถใช้NumberFormatter:

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

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

2
คำตอบที่ดีที่สุด
Codetard

(4.81).roundedDecimal(to: 2, mode: .down)จะคืนค่า 4.8 แทน 4.81 ใช้Decimal(string: self.description)!อย่างแม่นยำdecimalValue
vk.edward.li

1
@ vk.edward.li - ใช่คุณควรระวังเกี่ยวกับการปัดเศษทศนิยมขึ้น / ลงเพราะค่าเช่น 4.81 ไม่สามารถแสดงได้อย่างแม่นยำด้วยDouble(มันจะกลายเป็น4.8099999999999996) แต่ฉันแนะนำไม่ให้ใช้description(เนื่องจากการปัดเศษจะไม่มีการบันทึกไว้ในเอกสารและอาจมีการเปลี่ยนแปลง) ถ้าคุณอยากจะทำคณิตศาสตร์ทศนิยมที่ถูกต้องคุณควรหลีกเลี่ยงDoubleอย่างสิ้นเชิงและแทนที่จะควรใช้Decimalโดยตรง (เช่นDecimal(sign: .plus, exponent: -2, significand: 481)หรือDecimal(string: "4.81")แต่ไม่ได้ใช้. description.
ร็อบ

@Rob ปกติแล้วมันเป็นไปไม่ได้ที่จะได้รับค่าสตริงของ "4.81" ถ้ามันถูกเก็บเป็น Double ดังนั้นคุณต้องใช้ self.description (อัลกอริทึม Grisu2 ที่แก้ไขแล้ว) เพื่อแก้ไขความแม่นยำที่หายไปแล้ว
vk.edward.li

ฉันเข้าใจประเด็นของคุณ ฉันไม่เห็นด้วยกับวิธีแก้ปัญหาของคุณ พฤติกรรมการปัดเศษของdescriptionวิธีการไม่ได้รับการบันทึกหรือรับรอง นอกจากนี้ยังไม่มีการแปล IMHO เป็นความผิดพลาดที่จะใช้descriptionเพื่อวัตถุประสงค์อื่นนอกเหนือจากการบันทึก ฉันจะใช้Decimalตลอดหลีกเลี่ยงการใช้Doubleทั้งหมดหรือเพียงแค่ใช้โหมดการปัดเศษที่แตกต่างกัน หรือถ้าคุณต้องใช้วิธีการแปลของคุณเองที่ใช้อัลกอริทึมสไตล์ Grisu (แต่ดูเหมือนว่าไม่จำเป็นเมื่อคุณรู้จำนวนทศนิยมที่คุณต้องการปัดเศษ) descriptionแต่ฉันต้องการหลีกเลี่ยงการพึ่งพาพฤติกรรมเสริมนี้
Rob

8

นี่เป็นวิธีแก้ปัญหาที่ยาวนานซึ่งอาจมีประโยชน์หากความต้องการของคุณซับซ้อนกว่าเล็กน้อย คุณสามารถใช้ตัวจัดรูปแบบตัวเลขใน Swift

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

สมมติว่าตัวแปรที่คุณต้องการพิมพ์คือ

var printVar = 3.567

สิ่งนี้จะทำให้แน่ใจว่ามันจะถูกส่งกลับในรูปแบบที่ต้องการ:

numberFormatter.StringFromNumber(printVar)

ผลลัพธ์ที่นี่จะเป็น "3.6" (ปัดเศษ) ในขณะที่นี่ไม่ใช่ทางออกที่ประหยัดที่สุดฉันให้เพราะการพิมพ์ที่กล่าวถึง OP (ในกรณีที่ String ไม่พึงประสงค์) และเนื่องจากคลาสนี้อนุญาตให้มีการตั้งค่าพารามิเตอร์หลายรายการ


1
หมายเหตุสั้น ๆ ที่ฟอร์แมตใด ๆ ค่อนข้างแพงโดยทางโปรแกรมทำให้ไม่เหมาะกับงานที่ต้องดำเนินการอย่างรวดเร็วหรือซ้ำ ๆ
Jonathan Thornton

7

ฉันจะใช้

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

และเปลี่ยน. 3f เป็นจำนวนทศนิยมใด ๆ ที่คุณต้องการ


เขาต้องการที่จะพิมพ์ด้วยตัวเลข 3 หลักเพื่อไม่ให้ได้ใน NSTimeInterval
Mohsen Hossein เท

7

ทั้ง:

  1. การใช้String(format:):

    • Typecast DoubleถึงStringด้วยตัว%.3fระบุรูปแบบแล้วกลับไปที่Double

      Double(String(format: "%.3f", 10.123546789))!
    • หรือขยายDoubleเพื่อจัดการกับตำแหน่ง N-Decimal:

      extension Double {
          func rounded(toDecimalPlaces n: Int) -> Double {
              return Double(String(format: "%.\(n)f", self))!
          }
      }
  2. โดยการคำนวณ

    • คูณด้วย 10 ^ 3 ปัดเศษแล้วหารด้วย 10 ^ 3 ...

      (1000 * 10.123546789).rounded()/1000
    • หรือขยายDoubleเพื่อจัดการกับตำแหน่ง N-Decimal:

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

6

นี่คืออัลกอริทึมที่ยืดหยุ่นมากขึ้นของการปัดเศษเป็นตัวเลขนัยสำคัญ N

โซลูชัน Swift 3

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

วิธีที่ดีที่สุดในการจัดรูปแบบคุณสมบัติสองเท่าคือการใช้วิธีที่กำหนดไว้ล่วงหน้าของ Apple

mutating func round(_ rule: FloatingPointRoundingRule)

FloatingPointRoundingRule เป็น enum ซึ่งมีความเป็นไปได้ดังต่อไปนี้

กรณีการแจงนับ:

กรณีออกจาก FotoZero ปัดเศษเป็นค่าที่อนุญาตที่ใกล้เคียงที่สุดซึ่งมีขนาดมากกว่าหรือเท่ากับของแหล่งที่มา

ตัวพิมพ์เล็ก ปัดเศษเป็นค่าที่อนุญาตที่ใกล้เคียงที่สุดซึ่งน้อยกว่าหรือเท่ากับแหล่งที่มา

กรณี ที่ใกล้ที่สุดหรือห่างจากศูนย์ไปยังค่าที่อนุญาตที่ใกล้เคียงที่สุด; หากสองค่าใกล้กันเท่ากันค่าที่มีขนาดใหญ่กว่าจะถูกเลือก

case toNearestOrEven ปัดเศษเป็นค่าที่อนุญาตที่ใกล้เคียงที่สุด; หากสองค่าใกล้กันเท่ากันค่าที่เลือกจะถูกเลือก

กรณีไปที่ Zero Round ถึงค่าที่ใกล้เคียงที่สุดซึ่งมีขนาดน้อยกว่าหรือเท่ากับของแหล่งที่มา

case up ปัดเศษเป็นค่าที่อนุญาตที่ใกล้เคียงที่สุดซึ่งมากกว่าหรือเท่ากับแหล่งที่มา

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

6

รอบค่าคู่ x จำนวนทศนิยม
NO ของตัวเลขหลังทศนิยม

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

เกิดอะไรขึ้นกับรหัสนี้? ตัวอย่างทั้งสามแสดงให้เห็นถึงอะไร?
rene

คำตอบของรหัสเท่านั้นไม่มีประโยชน์โปรดลองอธิบายว่าแต่ละตัวอย่างเหล่านี้ทำอะไรได้บ้าง
Moe

5

ไม่ใช่ Swift แต่ฉันแน่ใจว่าคุณได้รับความคิด

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

4

ดูเหมือนว่าจะใช้งานได้ใน Swift 5

ค่อนข้างประหลาดใจที่ไม่มีฟังก์ชั่นมาตรฐานสำหรับสิ่งนี้อยู่แล้ว

// ตัดทอนของทศนิยมสองตำแหน่งเป็นทศนิยมด้วยการปัดเศษ

extension Double {

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

}

2

คุณสามารถเพิ่มส่วนขยายนี้:

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

และเรียกมันว่าสิ่งนี้:

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

อันนี้คือการนำไปปฏิบัติอย่างเรียบร้อยเพื่อแสดงว่ามันเป็นสายอักขระ ฉันสงสัยว่าเป็นไปได้หรือมีเหตุผลที่จะเขียนส่วนขยายของจำนวนตัวเลขที่เป็นตัวแทนหลังจากช่วงเวลาที่ยังคงเป็น Double
thinkswift

2

เพื่อหลีกเลี่ยงความไม่สมบูรณ์ของ Float ให้ใช้ทศนิยม

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

อดีต
1,075.58 รอบถึง 1,075.57 เมื่อใช้ Float ที่มีสเกล: 2 และ. ดาวน์
1075.58 รอบเป็น 1,075.58 เมื่อใช้ทศนิยมที่มีสเกล: 2 และ. down


1

ฉันพบสิ่งนี้สงสัยว่าเป็นไปได้หรือไม่ที่จะแก้ไขอินพุตของผู้ใช้ นั่นคือถ้าพวกเขาป้อนทศนิยมสามตำแหน่งแทนที่จะเป็นสองหน่วยเป็นดอลลาร์ พูด 1.111 แทนที่จะเป็น 1.11 คุณสามารถแก้ไขได้โดยปัดเศษ? คำตอบด้วยเหตุผลหลายประการคือไม่! ด้วยเงินจำนวนมากเช่น 0.001 ในที่สุดจะทำให้เกิดปัญหาในสมุดเช็คที่แท้จริง

นี่คือฟังก์ชั่นเพื่อตรวจสอบผู้ใช้ที่ป้อนค่ามากเกินไปหลังจากช่วงเวลา แต่จะอนุญาตให้ 1, 1.1 และ 1.11

สันนิษฐานว่าเป็นค่าที่ได้รับการตรวจสอบแล้วสำหรับการแปลงที่ประสบความสำเร็จจาก String เป็น Double

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

นี่คือส่วนหนึ่งสำหรับ SwiftUI หากคุณต้องการองค์ประกอบข้อความที่มีค่าตัวเลข

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

    var body : some View {
        Text(String(format: "%.\(digits)f", number))
    }
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.