Округление двойного значения до x число десятичных знаков в swift
может ли кто-нибудь сказать мне, как округлить двойное значение до x числа десятичных знаков в Swift?
Я:
var totalWorkTimeInHours = (totalWorkTime/60/60)
С totalWorkTime будучи NSTimeInterval (двойной) в секунду.
totalWorkTimeInHours даст мне часы, но это дает мне количество времени в таком длинном точном числе, например, 1.543240952039......
как мне округлить это до, скажем, 1.543, когда я печатаю totalWorkTimeInHours?
21 ответов:
вы можете использовать Swift
roundфункция для достижения этой цели.округлить
DoubleС точностью до 3 цифр сначала умножьте его на 1000, округлите и разделите округленный результат на 1000:let x = 1.23556789 let y = Double(round(1000*x)/1000) print(y) // 1.236другое, чем какой-либо
printf(...)илиString(format: ...)решения, результат этой операции по-прежнему имеет типDouble.EDIT:
Что касается комментариев, что это иногда не работает, пожалуйста, прочитайте это:что Каждый Компьютерный Ученый Должен Знать Об Арифметике С Плавающей Запятой
расширение для 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 } }
Пример, который возвращает двойное округление до 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
использовать
Stringконструктор, который принимаетformatстроку:print(String(format: "%.3f", totalWorkTimeInHours))
С Swift 4, в соответствии с вашими потребностями, вы можете выбрать один из 9 следующих стилей чтобы получить округленный результат от A
Double.
#1. Используя
FloatingPointrounded()методв самом простом случае, вы можете использовать
Doubleround()метод.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. Используя
FloatingPointrounded(_:)методvar roundedValue1 = (0.6844 * 1000).rounded(.toNearestOrEven) / 1000 var 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. Используя
NSDecimalNumberrounding(accordingToBehavior:)методпри необходимости
NSDecimalNumberпредлагает многословный, но мощный решение для округления десятичных чисел.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. Используя
NSStringinit(format:arguments:)инициализаторесли вы хотите вернуть
NSStringиз операции округления, используяNSStringинициализатор-это простое, но эффективное решение.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. Используя
Stringinit(format:_:)инициализаторСвифт
Stringтип соединяется с фондаNSStringкласса (вы можете узнать больше об этом, читая Язык Программирования Swift). Поэтому вы можете использовать следующий код для возврата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")
основываясь на ответе йога, вот быстрая функция, которая выполняет эту работу:
func roundToPlaces(value:Double, places:Int) -> Double { let divisor = pow(10.0, Double(places)) return round(value * divisor) / divisor }
это полностью отработанный код
Swift 3.0 / 4.0, Xcode 9.0 GM / 9.2
let doubleValue : Double = 123.32565254455 self.lblValue.text = String(format:"%.f", doubleValue) print(self.lblValue.text)выход - 123
self.lblValue_1.text = String(format:"%.1f", doubleValue) print(self.lblValue_1.text)выход - 123.3
self.lblValue_2.text = String(format:"%.2f", doubleValue) print(self.lblValue_2.text)выход - 123.33
self.lblValue_3.text = String(format:"%.3f", doubleValue) print(self.lblValue_3.text)выход - 123.326
в 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
код для конкретных цифр после десятичных знаков:
var a = 1.543240952039 var roundedString = String(format: "%.3f", a)сюда %.3f сообщает swift, чтобы это число было округлено до 3 десятичных знаков.и если вы хотите двойное число, вы можете использовать этот код:
// string в Double
var roundedString = Double(String(format: "%.3f", b))
удобный способ может быть использование расширение типа двойной
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
используйте встроенную библиотеку Фонда Дарвина
SWIFT 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
Это своего рода длительный обходной путь, который может пригодиться, если ваши потребности немного сложнее. Вы можете использовать форматер чисел в 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" (округленный). Хотя это не самое экономичное решение, я даю его, потому что ОП упомянула печать (в этом случае строка не нежелательно), и потому что этот класс позволяет устанавливать несколько параметров.
Я хотел бы использовать
print(String(format: "%.3f", totalWorkTimeInHours))и изменить .3f для любого количества десятичных чисел вам нужно
Не быстро, но я уверен, что вы поняли идею.
pow10np = pow(10,num_places); val = round(val*pow10np) / pow10np;
Это более гибкий алгоритм округления до 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
округлите двойное значение до X десятичного числа
НЕТ. цифр после десятичной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
лучший способ форматирования двойного свойства-использовать предопределенные методы Apple.
mutating func round(_ rule: FloatingPointRoundingRule)FloatingPointRoundingRule-это перечисление, которое имеет следующие возможности
Перечисление Случаях:
case awayFromZero Округление до ближайшего допустимого значения, величина которого больше или равна величине источника.
дело Округлить до ближайшего допустимого значения, которое меньше или равно к источнику.
case toNearestOrAwayFromZero Округление до ближайшего допустимого значения; если два значения одинаково близки, выбирается значение с большей величиной.
case toNearestOrEven Округление до ближайшего допустимого значения; если два значения одинаково близки, выбирается четное значение.
case towardZero Округлить до ближайшего допустимого значения, величина которого меньше или равна величине источник.
до Округление до ближайшего допустимого значения, которое больше или равно источнику.
var aNumber : Double = 5.2 aNumber.rounded(.up) // 6.0
либо:
используя
String(format:):
Typecast
DoubleдоStringС%.3fспецификатор формата, а затем обратно вDoubleDouble(String(format: "%.3f", 10.123546789))!или продлить
Doubleдля обработки N-десятичных знаков:extension Double { func rounded(toDecimalPlaces n: Int) -> Double { return Double(String(format: "%.\(n)f", self))! } }по расчету
умножить на 10^3, округлить и затем разделить на 10^3...
(1000 * 10.123546789).rounded()/1000или продлить
Doubleдля обработки N-десятичных знаков:extension Double { func rounded(toDecimalPlaces n: Int) -> Double { let multiplier = pow(10, Double(n)) return (multiplier * self).rounded()/multiplier } }
если ты хочешь
Doubleзначения, вы можете использовать SwiftDecimalтаким образом, вы не вводите никаких ошибок, которые могут возникнуть при попытке математики с этими округленными значениями. Если вы используете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) }
Я нашел это интересно, если можно исправить ввод пользователя. То есть, если они вводят три десятичных знака вместо двух для долларовой суммы. Сказать 1.111 вместо 1.11 вы можете исправить это путем округления? Ответ по многим причинам-нет! С деньгами все, что больше, т. е. 0.001, в конечном итоге вызовет проблемы в реальной чековой книжке.
вот функция для проверки ввода пользователя слишком много значения после периода. Но что позволит 1., 1.1 и 1.11.
Это предполагается, что значение уже было проверено на успешное преобразование из строки в двойник.
//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 }
//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"

Comments