在swift中,将双精度值舍入到小数点后x位

谁能告诉我如何在Swift中舍入一个双数值到x位小数点后数位?

我有:

var totalWorkTimeInHours = (totalWorkTime/60/60)

totalWorkTime是一个以秒为单位的NSTimeInterval (double)。

totalWorkTimeInHours将给我小时,但它给我时间的数量在这样一个很长的精确数字,例如1.543240952039......

当我打印totalWorkTimeInHours时,我如何四舍五入到,比如说,1.543 ?

536948 次浏览

不是斯威夫特,但我相信你明白我的意思。

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

我如何四舍五入到,比如说,1.543 当我打印时 totalWorkTimeInHours?

要将totalWorkTimeInHours四舍五入为3位进行打印,使用String构造函数,该构造函数接受一个format字符串:

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

你可以使用Swift的round函数来实现这一点。

要以3位精度舍入Double,首先将其乘以1000,舍入并将舍入结果除以1000:

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

与任何类型的printf(...)String(format: ...)解决方案不同,此操作的结果仍然是类型Double

< p > 编辑:
关于它有时不工作的评论,请阅读这个:关于浮点运算,每个程序员都应该知道的

基于Yogi的回答,这里有一个Swift函数来完成这项工作:

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

一个方便的方法是使用类型的扩展

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 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中,roundrounded取代:

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
}
}
< p >
示例,返回四舍五入到小数点后4位的Double:

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

在Swift 5.5和Xcode 13.2中:

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

例子:

舍入双值

附注:自Swift 2.0和Xcode 7.2以来一直如此

我想知道是否有可能纠正用户的输入。也就是说,如果他们输入三个小数而不是两个小数来表示一美元的金额。比如说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




}

这是一种长期的变通方法,如果您的需求稍微复杂一点,它可能会派上用场。你可以在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不是不可取的),并且因为该类允许设置多个参数。

在Swift 5中,根据你的需要,你可以从9以下风格中选择一个,以便从Double中得到四舍五入的结果。


# 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。使用Darwin round函数

Foundation通过Darwin提供了一个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。使用由Darwin roundpow函数构建的Double扩展自定义方法

如果您想多次重复前面的操作,重构代码可能是一个好主意。

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提供了一个详细但强大的十进制数字舍入解决方案。

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:)初始化器

如果你想从舍入操作返回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。使用String init(format:_:)初始化器

Swift的String类型与Foundation的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")

我会用

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

然后把。3f改成任何你需要的十进制数

在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

这是一个更灵活的算法舍入到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

使用内置的达尔文基金会图书馆

斯威夫特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

格式化double属性的最好方法是使用Apple预定义的方法。

mutating func round(_ rule: FloatingPointRoundingRule)

FloatingPointRoundingRule是一个枚举,有以下几种可能

枚举的案例:

< >强awayFromZero 四舍五入到最接近的允许值,其大小大于或等于源值

< >强情况下下来 四舍五入到小于或等于源的最接近的允许值

< >强toNearestOrAwayFromZero 四舍五入到最接近的允许值;如果两个值相等,则选择大小较大的值

< >强toNearestOrEven 四舍五入到最接近的允许值;如果两个值相等,则选择偶数

< >强towardZero 四舍五入到最接近的允许值,其大小小于或等于源值

< >强情况下 四舍五入到最接近的允许值,该值大于或等于源值

var aNumber : Double = 5.2
aNumber.rounded(.up) // 6.0
< p > 二重值舍入到小数的x位 < br > 不。小数点后的数字

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

这是一个完整的代码

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

如果你想对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)
}

小数点后特定数字的代码为:

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

这里是%。3f告诉swift将这个数字四舍五入到小数点后3位。如果你想要双倍的数字,你可以使用这个代码:

//字符串为Double

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

//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. 使用String(format:) < p >:

    • 使用%.3f格式说明符将Double类型转换为String,然后再转换回Double

      Double(String(format: "%.3f", 10.123546789))!
      
    • Or extend Double to handle N-Decimal places:

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

    • multiply with 10^3, round it and then divide by 10^3...

      (1000 * 10.123546789).rounded()/1000
      
    • Or extend Double to handle N-Decimal places:

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

Swift 4, Xcode 10

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

你可以添加这个扩展:

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

这在Swift 5中似乎有效。

令人惊讶的是,现在还没有这样的标准函数。

//用四舍五入截断双位数到小数点后n位

extension Double {


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


}

这里有一个SwiftUI,如果你需要一个文本元素的数字值。

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


var body : some View {
Text(String(format: "%.\(digits)f", number))
}
}

为了避免Float不完美,请使用Decimal

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
}
}
< p > 前女友。 < br > 当使用Float且比例为2和.down
时,1075.58四舍五入为1075.57 1075.58在使用Decimal时四舍五入为1075.58,并且使用。down

var n = 123.111222333
n = Double(Int(n * 10.0)) / 10.0

结果:n = 123.1

将10.0(小数点后1位)更改为100.0(小数点后2位)、1000.0(小数点后3位)中的任意一个,以此作为您想要的小数后的位数。

如果你想在逗号后面只有0表示圆,试试这个:

extension Double {
func isInteger() -> Any {
let check = floor(self) == self
if check {
return Int(self)
} else {
return self
}
}
}


let toInt: Double = 10.0
let stillDouble: Double = 9.12


print(toInt.isInteger) // 10
print(stillDouble.isInteger) // 9.12

斯威夫特5

使用字符串方法

var yourDouble = 3.12345
//to round this to 2 decimal spaces i could turn it into string
let roundingString = String(format: "%.2f", myDouble)
let roundedDouble = Double(roundingString) //and than back to double
// result is 3.12

但是使用扩展更容易被接受

extension Double {
func round(to decimalPlaces: Int) -> Double {
let precisionNumber = pow(10,Double(decimalPlaces))
var n = self // self is a current value of the Double that you will round
n = n * precisionNumber
n.round()
n = n / precisionNumber
return n
}
}

然后你可以使用:

yourDouble.round(to:2)

很多例子都使用数学,问题是浮动近似真实的号码,没有办法表达0.1(1/10)就像一个漂浮一样没有准确的方式来表达⅓完全使用小数点,所以你需要问你自己你正试图实现什么,如果你只是想显示他们离开他们的代码,试图轮他们是准确的结果会证明给你少你扔掉珍贵,如果你有一个类似viewModel类的东西,它可以用来返回一个字符串来表示你的模型的数字。numberformatters为您提供了大量关于如何格式化数字和您想要的小数位数的控制。

这个解决方案对我很有效。XCode 13.3.1 &斯威夫特5

extension Double {
    

func rounded(decimalPoint: Int) -> Double {
let power = pow(10, Double(decimalPoint))
return (self * power).rounded() / power
}
}

测试:

print(-87.7183123123.rounded(decimalPoint: 3))
print(-87.7188123123.rounded(decimalPoint: 3))
print(-87.7128123123.rounded(decimalPoint: 3))

结果:

-87.718
-87.719
-87.713

对于许多应用程序,需要精确的小数位数来舍入。

对于其他一些人,你没有这样的约束,想要“压缩”;输出大小,但仍然希望避免将数字转换为字符串(反之亦然),就像在导出JSON有数百万个数字。

在这种情况下,您可以使用'trick'来四舍五入有效数(尾数),而不是整数。在这种情况下,你会得到最后的小数点 大多数数字仍然最多保留3位小数点后数位(如果需要的话),而有些数字会稍微多一些

这是你在使用十进制数时所期望的结果:

5.2472

5.2516

5.2556

5.26

5.264

而不是:

5.24731462499949

5.251488374999099

5.25566283399894

5.259839374999501

5.264012208999702

let value = 5.24731462499949


print(value)
// 5.24731462499949


let valueSignificandRounded = round((1000 * 10) * value.significand) / (1000 * 10)


let valueRounded = CGFloat(sign: v.sign, exponent: v.exponent, significand: valueSignificandRounded)


print(valueRounded)
// 5.2472

为了方便使用,我创建了一个扩展:

extension Double {
var threeDigits: Double {
return (self * 1000).rounded(.toNearestOrEven) / 1000
}
    

var twoDigits: Double {
return (self * 100).rounded(.toNearestOrEven) / 100
}
    

var oneDigit: Double {
return (self * 10).rounded(.toNearestOrEven) / 10
}
}


var myDouble = 0.12345
print(myDouble.threeDigits)
print(myDouble.twoDigits)
print(myDouble.oneDigit)

打印结果如下:

0.123
0.12
0.1

感谢其他答案的启发!

Swift最佳方式

这就是我把四舍五入到小数点后两位的方法

let val = round(100 * scale) / 100