How to get the integer part and fractional part of a number in Swift - swift

This is a super basic question, but, I can't seem to find an answer in Swift.
Question:
How do I get the whole integer part and fractional part (to the left and right of the decimal point respectively) of a number in Swift 2 and Swift 3? For example, for the number 1234.56789 —
How do I get the integer part 1234.56789 ?
How do I get the fractional part 1234.56789 ?

You could do simple floor and truncating:
let value = 1234.56789
let double = floor(value) // 1234.0
let integer = Int(double) // 1234
let decimal = value.truncatingRemainder(dividingBy: 1) // 0.56789

No need for extensions. Swift already has built in function for this.
let aNumber = modf(3.12345)
aNumber.0 // 3.0
aNumber.1 // 0.12345

Swift 4.xm, 5.x complete solution:
I credit #Thomas solution also I'd like to add few things which allow us to use separated parts in 2 string part.
Especially when we want to use 2 different UILabel for main and decimal part of the number.
Extension below is also managing number quantity of decimal part. I thought it might be useful.
UPDATE: Now, it is working perfectly with negative numbers as well!
public extension Double{
func integerPart()->String{
let result = floor(abs(self)).description.dropLast(2).description
let plusMinus = self < 0 ? "-" : ""
return plusMinus + result
}
func fractionalPart(_ withDecimalQty:Int = 2)->String{
let valDecimal = self.truncatingRemainder(dividingBy: 1)
let formatted = String(format: "%.\(withDecimalQty)f", valDecimal)
let dropQuantity = self < 0 ? 3:2
return formatted.dropFirst(dropQuantity).description
}

Convert your number into String later separate string from .
Try this:-
let number:Float = 123.46789
let numberString = String(number)
let numberComponent = numberString.components(separatedBy :".")
let integerNumber = Int(numberComponent [0])
let fractionalNumber = Int(numberComponent [1])

You could do this ->
let x:Double = 1234.5678
let y:Double = Double(Int(x))
let z:Double = x - Double(Int(x))
print("\(x) \(y) \(z)")
Where x is your original value. y is the integer part and z is the fractional part.
Edit
Thomas answer is the one you want ...

This will definitely work for you in swift 5 and 4
let number = 3.145443
let integerValue = String(format: "%.0f", number)
let integerValue1 = String(format: "%.1f", number)
let integerValue2 = String(format: "%.2f", number)
print(integerValue)
print(integerValue1)
print(integerValue2)
//Output
3
3.1
3.14

modf() works bad with numbers > 1 billion
#Trevor behaves like modf()
#Andres Cedronius example behaves like modf() too (i tried modify it)
#Irshad Ahmed solution is nice
there is some convenience convertions
For some reason you need more control, check out https://developer.apple.com/documentation/foundation/numberformatter
extension Double {
/// 1.00234 -> 1.0
var integerPart: Double {
return Double(Int(self))
}
/// 1.0012 --> 0.0012
var fractionPart: Double {
let fractionStr = "0.\(String(self).split(separator: ".")[1])"
return Double(fractionStr)!
}
/// 1.0012 --> "0.0012"
var fractionPartString: String {
return "0.\(String(self).split(separator: ".")[1])"
}
/// 1.0012 --> 12
var fractionPartInteger: Int {
let fractionStr = "\(String(self).split(separator: ".")[1])"
return Int(fractionStr)!
}
}
print(1000.0.integerPart) // 1000.0
print(1000.0.fractionPart) // 0.0
print(1000.1.integerPart) // 1000.0
print(1000.2.fractionPart) // 0.2
print(1_000_000_000.1.integerPart) // 1000000000.0
print(100_000_000.13233.fractionPart) // 0.13233

var specimen0:Double = 1234.56789
var significant0 = Double.IntegerLiteralType(specimen0) // result is an integer
var fractionals0 = specimen0 - Double(significant0)
var specimen1:Float = -1234.56789
var significant1 = Float.IntegerLiteralType(specimen1) // result is an integer
var fractionals1 = specimen1 - Float(significant1)
var specimen2:CGFloat = -1234.56789
var significant2 = CGFloat.IntegerLiteralType(specimen2) // result is an integer
var fractionals2 = specimen2 - CGFloat(significant2)
These are all built in as of Swift 5.3, I am sure even earlier...

Related

How to properly reduce scale and format a Float value in Swift?

I'm trying to properly reduce scale, formatting a float value and returning it as a String in Swift.
For example:
let value: Float = 4.8962965
// formattedFalue should be 4.90 or 4,90 based on localization
let formattedValue = value.formatNumber()
Here is what I did:
extension Float {
func reduceScale(to places: Int) -> Float {
let multiplier = pow(10, Float(places))
let newDecimal = multiplier * self // move the decimal right
let truncated = Float(Int(newDecimal)) // drop the fraction
let originalDecimal = truncated / multiplier // move the decimal back return originalDecimal
}
func formatNumber() -> String {
let num = abs(self)
let numberFormatter = NumberFormatter()
numberFormatter.usesGroupingSeparator = true
numberFormatter.minimumFractionDigits = 0
numberFormatter.maximumFractionDigits = 2
numberFormatter.roundingMode = .up
numberFormatter.numberStyle = .decimal
numberFormatter.locale = // we take it from app settings
let formatted = num.reduceScale(to: 2)
let returningString = numberFormatter.string(from: NSNumber(value: formatted))!
return "\(returningString)"
}
}
But when I use this code I get 4.89 (or 4,89 depending on the localization) instead of 4.90 (or 4,90) as I expect.
Thanks in advance.
You get 4.89 because reduceScale(to:) turns the number into 4.89 (actually, probably 4.89000something because 4.89 cannot be expressed exactly as a binary floating point). When the number formatter truncates this to two decimal places, it naturally rounds it down.
In fact, you don't need reduceScale(to:) at all because the rounding function of the number formatter will do it for you.
Also the final string interpolation is unnecessary because the result of NumberFormatter.string(from:) is automatically bridged to a String?
Also (see comments below by Dávid Pásztor and Sulthan) you can use string(for:) to obviate the NSNumber conversion.
This is what you need
import Foundation
extension Float {
func formatNumber() -> String {
let num = abs(self)
let numberFormatter = NumberFormatter()
numberFormatter.usesGroupingSeparator = true
numberFormatter.minimumFractionDigits = 0
numberFormatter.maximumFractionDigits = 2
numberFormatter.roundingMode = .up
numberFormatter.numberStyle = .decimal
numberFormatter.locale = whatever
return numberFormatter.string(for: num)!
}
}
let value: Float = 4.8962965
// formattedFalue should be 4.90 or 4,90 based on localization
let formattedValue = value.formatNumber() // "4.9"
Solved by following Sulthan's comments:
remove that reduceScale method which is not necessary and it will probably work as expected. You are truncating the decimal to 4.89 which cannot be rounded any more (it is already rounded). – Sulthan 6 hours ago
That's because you have specified minimumFractionDigits = 0. If you always want to display two decimal digits, you will have to set minimumFractionDigits = 2. – Sulthan 5 hours ago
Foundation has a better API now.
In-place, you can use .number:
value.formatted(.number
.precision(.fractionLength(2))
.locale(locale)
)
But it's only available on specific types. For an extension for more than one floating-point type, you'll need to use the equivalent initializer instead:
extension BinaryFloatingPoint {
var formattedTo2Places: String {
formatted(FloatingPointFormatStyle()
.precision(.fractionLength(2))
.locale(locale)
)
}
}
let locale = Locale(identifier: "it")
(4.8962965 as Float).formattedTo2Places // 4,90

Split fractional and integral parts of a Double [duplicate]

I'm trying to separate the decimal and integer parts of a double in swift. I've tried a number of approaches but they all run into the same issue...
let x:Double = 1234.5678
let n1:Double = x % 1.0 // n1 = 0.567800000000034
let n2:Double = x - 1234.0 // same result
let n3:Double = modf(x, &integer) // same result
Is there a way to get 0.5678 instead of 0.567800000000034 without converting to the number to a string?
You can use truncatingRemainder and 1 as the divider.
Returns the remainder of this value divided by the given value using truncating division.
Apple doc
Example:
let myDouble1: Double = 12.25
let myDouble2: Double = 12.5
let myDouble3: Double = 12.75
let remainder1 = myDouble1.truncatingRemainder(dividingBy: 1)
let remainder2 = myDouble2.truncatingRemainder(dividingBy: 1)
let remainder3 = myDouble3.truncatingRemainder(dividingBy: 1)
remainder1 -> 0.25
remainder2 -> 0.5
remainder3 -> 0.75
Same approach as Alessandro Ornano implemented as an instance property of FloatingPoint protocol:
Xcode 11 • Swift 5.1
import Foundation
extension FloatingPoint {
var whole: Self { modf(self).0 }
var fraction: Self { modf(self).1 }
}
1.2.whole // 1
1.2.fraction // 0.2
If you need the fraction digits and preserve its precision digits you would need to use Swift Decimal type and initialize it with a String:
extension Decimal {
func rounded(_ roundingMode: NSDecimalNumber.RoundingMode = .plain) -> Decimal {
var result = Decimal()
var number = self
NSDecimalRound(&result, &number, 0, roundingMode)
return result
}
var whole: Decimal { rounded(sign == .minus ? .up : .down) }
var fraction: Decimal { self - whole }
}
let decimal = Decimal(string: "1234.99999999")! // 1234.99999999
let fractional = decimal.fraction // 0.99999999
let whole = decimal.whole // 1234
let sum = whole + fractional // 1234.99999999
let negativeDecimal = Decimal(string: "-1234.99999999")! // -1234.99999999
let negativefractional = negativeDecimal.fraction // -0.99999999
let negativeWhole = negativeDecimal.whole // -1234
let negativeSum = negativeWhole + negativefractional // -1234.99999999
Swift 2:
You can use:
modf(x).1
or
x % floor(abs(x))
Without converting it to a string, you can round up to a number of decimal places like this:
let x:Double = 1234.5678
let numberOfPlaces:Double = 4.0
let powerOfTen:Double = pow(10.0, numberOfPlaces)
let targetedDecimalPlaces:Double = round((x % 1.0) * powerOfTen) / powerOfTen
Your output would be
0.5678
Swift 5.1
let x:Double = 1234.5678
let decimalPart:Double = x.truncatingRemainder(dividingBy: 1) //0.5678
let integerPart:Double = x.rounded(.towardZero) //1234
Both of these methods return Double value.
if you want an integer number as integer part, you can just use
Int(x)
Use Float since it has less precision digits than Double
let x:Double = 1234.5678
let n1:Float = Float(x % 1) // n1 = 0.5678
There’s a function in C’s math library, and many programming languages, Swift included, give you access to it. It’s called modf, and in Swift, it works like this
// modf returns a 2-element tuple,
// with the whole number part in the first element,
// and the fraction part in the second element
let splitPi = modf(3.141592)
splitPi.0 // 3.0
splitPi.1 // 0.141592
You can create an extension like below,
extension Double {
func getWholeNumber() -> Double {
return modf(self).0
}
func getFractionNumber() -> Double {
return modf(self).1
}
}
You can get the Integer part like this:
let d: Double = 1.23456e12
let intparttruncated = trunc(d)
let intpartroundlower = Int(d)
The trunc() function truncates the part after the decimal point and the Int() function rounds to the next lower value. This is the same for positive numbers but a difference for negative numbers. If you subtract the truncated part from d, then you will get the fractional part.
func frac (_ v: Double) -> Double
{
return (v - trunc(v))
}
You can get Mantissa and Exponent of a Double value like this:
let d: Double = 1.23456e78
let exponent = trunc(log(d) / log(10.0))
let mantissa = d / pow(10, trunc(log(d) / log(10.0)))
Your result will be 78 for the exponent and 1.23456 for the Mantissa.
Hope this helps you.
It's impossible to create a solution that will work for all Doubles. And if the other answers ever worked, which I also believe is impossible, they don't anymore.
let _5678 = 1234.5678.description.drop { $0 != "." } .description // ".5678"
Double(_5678) // 0.5678
let _567 = 1234.567.description.drop { $0 != "." } .description // ".567"
Double(_567) // 0.5669999999999999
extension Double {
/// Gets the decimal value from a double.
var decimal: Double {
Double("0." + string.split(separator: ".").last.string) ?? 0.0
}
var string: String {
String(self)
}
}
This appears to solve the Double precision issues.
Usage:
print(34.46979988898988.decimal) // outputs 0.46979988898988
print(34.46.decimal) // outputs 0.46

Round up double to 2 decimal places

How do I round up currentRatio to two decimal places?
let currentRatio = Double (rxCurrentTextField.text!)! / Double (txCurrentTextField.text!)!
railRatioLabelField.text! = "\(currentRatio)"
Use a format string to round up to two decimal places and convert the double to a String:
let currentRatio = Double (rxCurrentTextField.text!)! / Double (txCurrentTextField.text!)!
railRatioLabelField.text! = String(format: "%.2f", currentRatio)
Example:
let myDouble = 3.141
let doubleStr = String(format: "%.2f", myDouble) // "3.14"
If you want to round up your last decimal place, you could do something like this (thanks Phoen1xUK):
let myDouble = 3.141
let doubleStr = String(format: "%.2f", ceil(myDouble*100)/100) // "3.15"
(Swift 4.2 Xcode 11)
Simple to use Extension:-
extension Double {
func round(to places: Int) -> Double {
let divisor = pow(10.0, Double(places))
return (self * divisor).rounded() / divisor
}
}
Use:-
if let distanceDb = Double(strDistance) {
cell.lblDistance.text = "\(distanceDb.round(to:2)) km"
}
Updated to SWIFT 4 and the proper answer for the question
If you want to round up to 2 decimal places you should multiply with 100 then round it off and then divide by 100
var x = 1.5657676754
var y = (x*100).rounded()/100
print(y) // 1.57
Consider using NumberFormatter for this purpose, it provides more flexibility if you want to print the percentage sign of the ratio or if you have things like currency and large numbers.
let amount = 10.000001
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
formatter.maximumFractionDigits = 2
let formattedAmount = formatter.string(from: amount as NSNumber)!
print(formattedAmount) // 10
Adding to above answer if we want to format Double multiple times, we can use protocol extension of Double like below:
extension Double {
var dollarString:String {
return String(format: "$%.2f", self)
}
}
let a = 45.666
print(a.dollarString) //will print "$45.67"
Just a quick follow-up answer for noobs like me:
You can make the other answers super easily implementable by using a function with an output. E.g.
func twoDecimals(number: Float) -> String{
return String(format: "%.2f", number)
}
This way, whenever you want to grab a value to 2 decimal places you just type
twoDecimals('Your number here')
...
Simples!
P.s. You could also make it return a Float value, or anything you want, by then converting it again after the String conversion as follows:
func twoDecimals(number: Float) -> Float{
let stringValue = String(format: "%.2f", number)
return Float(stringValue)!
}
Hope that helps.
The code for specific digits after decimals is:
var roundedString = String(format: "%.2f", currentRatio)
Here the %.2f tells the swift to make this number rounded to 2 decimal places.
#Rounded, A swift 5.1 property wrapper
Example :
struct GameResult {
#Rounded(rule: NSDecimalNumber.RoundingMode.up,scale: 4)
var score: Decimal
}
var result = GameResult()
result.score = 3.14159265358979
print(result.score) // 3.1416
Maybe also:
// Specify the decimal place to round to using an enum
public enum RoundingPrecision {
case ones
case tenths
case hundredths
case thousands
}
extension Double {
// Round to the specific decimal place
func customRound(_ rule: FloatingPointRoundingRule, precision: RoundingPrecision = .ones) -> Double {
switch precision {
case .ones: return (self * Double(1)).rounded(rule) / 1
case .tenths: return (self * Double(10)).rounded(rule) / 10
case .hundredths: return (self * Double(100)).rounded(rule) / 100
case .thousands: return (self * Double(1000)).rounded(rule) / 1000
}
}
}
let value: Double = 98.163846
print(value.customRound(.toNearestOrEven, precision: .ones)) //98.0
print(value.customRound(.toNearestOrEven, precision: .tenths)) //98.2
print(value.customRound(.toNearestOrEven, precision: .hundredths)) //98.16
print(value.customRound(.toNearestOrEven, precision: .thousands)) //98.164
Keeps decimals, does not truncate but rounds
See for more details even specified rounding rules
String(format: "%.2f", Double(round(1000*34.578)/1000))
Output: 34.58
Try this , you will get a better result instead of 0.0
extension Double {
func rounded(toPlaces places:Int) -> Double {
let divisor = pow(10.0, Double(places))
return (self * divisor).rounded() / divisor
}
func toRoundedString(toPlaces places:Int) -> String {
let amount = self.rounded(toPlaces: places)
let str_mount = String(amount)
let sub_amountStrings = str_mount.split(separator: ".")
if sub_amountStrings.count == 1
{
var re_str = "\(sub_amountStrings[0])."
for _ in 0..<places
{
re_str += "0"
}
return re_str
}
else if sub_amountStrings.count > 1, "\(sub_amountStrings[1])".count < places
{
var re_str = "\(sub_amountStrings[0]).\(sub_amountStrings[1])"
let tem_places = (places - "\(sub_amountStrings[1])".count)
for _ in 0..<tem_places
{
re_str += "0"
}
return re_str
}
return str_mount
}
}
if you give it 234.545332233 it will give you 234.54
let textData = Double(myTextField.text!)!
let text = String(format: "%.2f", arguments: [textData])
mylabel.text = text
Just single line of code:
let obj = self.arrayResult[indexPath.row]
let str = String(format: "%.2f", arguments: [Double((obj.mainWeight)!)!])

Rounding a double value to x number of decimal places in swift

Can anyone tell me how to round a double value to x number of decimal places in Swift?
I have:
var totalWorkTimeInHours = (totalWorkTime/60/60)
With totalWorkTime being an NSTimeInterval (double) in second.
totalWorkTimeInHours will give me the hours, but it gives me the amount of time in such a long precise number e.g. 1.543240952039......
How do I round this down to, say, 1.543 when I print totalWorkTimeInHours?
You can use Swift's round function to accomplish this.
To round a Double with 3 digits precision, first multiply it by 1000, round it and divide the rounded result by 1000:
let x = 1.23556789
let y = Double(round(1000 * x) / 1000)
print(y) /// 1.236
Unlike any kind of printf(...) or String(format: ...) solutions, the result of this operation is still of type Double.
EDIT:
Regarding the comments that it sometimes does not work, please read this: What Every Programmer Should Know About Floating-Point Arithmetic
Extension for Swift 2
A more general solution is the following extension, which works with 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
}
}
Extension for Swift 3
In Swift 3 round is replaced by 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
}
}
Example which returns Double rounded to 4 decimal places:
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
How do I round this down to, say, 1.543 when I print totalWorkTimeInHours?
To round totalWorkTimeInHours to 3 digits for printing, use the String constructor which takes a format string:
print(String(format: "%.3f", totalWorkTimeInHours))
With Swift 5, according to your needs, you can choose one of the 9 following styles in order to have a rounded result from a Double.
#1. Using FloatingPoint rounded() method
In the simplest case, you may use the Double rounded() method.
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. Using FloatingPoint rounded(_:) method
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. Using Darwin round function
Foundation offers a round function via Darwin.
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. Using a Double extension custom method built with Darwin round and pow functions
If you want to repeat the previous operation many times, refactoring your code can be a good idea.
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. Using NSDecimalNumber rounding(accordingToBehavior:) method
If needed, NSDecimalNumber offers a verbose but powerful solution for rounding decimal numbers.
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. Using NSDecimalRound(_:_:_:_:) function
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. Using NSString init(format:arguments:) initializer
If you want to return a NSString from your rounding operation, using NSString initializer is a simple but efficient solution.
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. Using String init(format:_:) initializer
Swift’s String type is bridged with Foundation’s NSString class. Therefore, you can use the following code in order to return a String from your rounding operation:
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. Using NumberFormatter
If you expect to get a String? from your rounding operation, NumberFormatter offers a highly customizable solution.
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")
In Swift 5.5 and Xcode 13.2:
let pi: Double = 3.14159265358979
String(format:"%.2f", pi)
Example:
PS.: It still the same since Swift 2.0 and Xcode 7.2
This is a fully worked code
Swift 3.0/4.0/5.0 , Xcode 9.0 GM/9.2 and above
let doubleValue : Double = 123.32565254455
self.lblValue.text = String(format:"%.f", doubleValue)
print(self.lblValue.text)
output - 123
let doubleValue : Double = 123.32565254455
self.lblValue_1.text = String(format:"%.1f", doubleValue)
print(self.lblValue_1.text)
output - 123.3
let doubleValue : Double = 123.32565254455
self.lblValue_2.text = String(format:"%.2f", doubleValue)
print(self.lblValue_2.text)
output - 123.33
let doubleValue : Double = 123.32565254455
self.lblValue_3.text = String(format:"%.3f", doubleValue)
print(self.lblValue_3.text)
output - 123.326
Building on Yogi's answer, here's a Swift function that does the job:
func roundToPlaces(value:Double, places:Int) -> Double {
let divisor = pow(10.0, Double(places))
return round(value * divisor) / divisor
}
In Swift 3.0 and Xcode 8.0:
extension Double {
func roundTo(places: Int) -> Double {
let divisor = pow(10.0, Double(places))
return (self * divisor).rounded() / divisor
}
}
Use this extension like so:
let doubleValue = 3.567
let roundedValue = doubleValue.roundTo(places: 2)
print(roundedValue) // prints 3.56
Swift 4, Xcode 10
yourLabel.text = String(format:"%.2f", yourDecimalValue)
The code for specific digits after decimals is:
var a = 1.543240952039
var roundedString = String(format: "%.3f", a)
Here the %.3f tells the swift to make this number rounded to 3 decimal places.and if you want double number, you may use this code:
// String to Double
var roundedString = Double(String(format: "%.3f", b))
Use the built in Foundation Darwin library
SWIFT 3
extension Double {
func round(to places: Int) -> Double {
let divisor = pow(10.0, Double(places))
return Darwin.round(self * divisor) / divisor
}
}
Usage:
let number:Double = 12.987654321
print(number.round(to: 3))
Outputs: 12.988
If you want to round Double values, you might want to use Swift Decimal so you don't introduce any errors that can crop up when trying to math with these rounded values. If you use Decimal, it can accurately represent decimal values of that rounded floating point value.
So you can do:
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
}
}
Then, you can get the rounded Decimal value like so:
let foo = 427.3000000002
let value = foo.roundedDecimal(to: 2) // results in 427.30
And if you want to display it with a specified number of decimal places (as well as localize the string for the user's current locale), you can use a NumberFormatter:
let formatter = NumberFormatter()
formatter.maximumFractionDigits = 2
formatter.minimumFractionDigits = 2
if let string = formatter.string(for: value) {
print(string)
}
A handy way can be the use of extension of type Double
extension Double {
var roundTo2f: Double {return Double(round(100 *self)/100) }
var roundTo3f: Double {return Double(round(1000*self)/1000) }
}
Usage:
let regularPie: Double = 3.14159
var smallerPie: Double = regularPie.roundTo3f // results 3.142
var smallestPie: Double = regularPie.roundTo2f // results 3.14
This is a sort of a long workaround, which may come in handy if your needs are a little more complex. You can use a number formatter in Swift.
let numberFormatter: NSNumberFormatter = {
let nf = NSNumberFormatter()
nf.numberStyle = .DecimalStyle
nf.minimumFractionDigits = 0
nf.maximumFractionDigits = 1
return nf
}()
Suppose your variable you want to print is
var printVar = 3.567
This will make sure it is returned in the desired format:
numberFormatter.StringFromNumber(printVar)
The result here will thus be "3.6" (rounded). While this is not the most economic solution, I give it because the OP mentioned printing (in which case a String is not undesirable), and because this class allows for multiple parameters to be set.
Either:
Using String(format:):
Typecast Double to String with %.3f format specifier and then back to 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))!
}
}
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
}
}
I would use
print(String(format: "%.3f", totalWorkTimeInHours))
and change .3f to any number of decimal numbers you need
This is more flexible algorithm of rounding to N significant digits
Swift 3 solution
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
The best way to format a double property is to use the Apple predefined methods.
mutating func round(_ rule: FloatingPointRoundingRule)
FloatingPointRoundingRule is a enum which has following possibilities
Enumeration Cases:
case awayFromZero
Round to the closest allowed value whose magnitude is greater than or equal to that of the source.
case down
Round to the closest allowed value that is less than or equal to the source.
case toNearestOrAwayFromZero
Round to the closest allowed value; if two values are equally close, the one with greater magnitude is chosen.
case toNearestOrEven
Round to the closest allowed value; if two values are equally close, the even one is chosen.
case towardZero
Round to the closest allowed value whose magnitude is less than or equal to that of the source.
case up
Round to the closest allowed value that is greater than or equal to the source.
var aNumber : Double = 5.2
aNumber.rounded(.up) // 6.0
round a double value to x number of decimal
NO. of digits after decimal
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
For ease to use, I created an extension:
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)
The print results are:
0.123
0.12
0.1
Thanks for the inspiration of other answers!
Not Swift but I'm sure you get the idea.
pow10np = pow(10,num_places);
val = round(val*pow10np) / pow10np;
Swift 5
using String method
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
but it's more accepted to use extension
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
}
}
and then you can use:
yourDouble.round(to:2)
This seems to work in Swift 5.
Quite surprised there isn't a standard function for this already.
//Truncation of Double to n-decimal places with rounding
extension Double {
func truncate(to places: Int) -> Double {
return Double(Int((pow(10, Double(places)) * self).rounded())) / pow(10, Double(places))
}
}
To avoid Float imperfections use 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
}
}
ex.
1075.58 rounds to 1075.57 when using Float with scale: 2 and .down
1075.58 rounds to 1075.58 when using Decimal with scale: 2 and .down
var n = 123.111222333
n = Double(Int(n * 10.0)) / 10.0
Result: n = 123.1
Change 10.0 (1 decimal place) to any of 100.0 (2 decimal place), 1000.0 (3 decimal place) and so on, for the number of digits you want after decimal..
The solution worked for me. XCode 13.3.1 & Swift 5
extension Double {
func rounded(decimalPoint: Int) -> Double {
let power = pow(10, Double(decimalPoint))
return (self * power).rounded() / power
}
}
Test:
print(-87.7183123123.rounded(decimalPoint: 3))
print(-87.7188123123.rounded(decimalPoint: 3))
print(-87.7128123123.rounded(decimalPoint: 3))
Result:
-87.718
-87.719
-87.713
I found this wondering if it is possible to correct a user's input. That is if they enter three decimals instead of two for a dollar amount. Say 1.111 instead of 1.11 can you fix it by rounding? The answer for many reasons is no! With money anything over i.e. 0.001 would eventually cause problems in a real checkbook.
Here is a function to check the users input for too many values after the period. But which will allow 1., 1.1 and 1.11.
It is assumed that the value has already been checked for successful conversion from a String to a 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
}
You can add this extension :
extension Double {
var clean: String {
return self.truncatingRemainder(dividingBy: 1) == 0 ? String(format: "%.0f", self) : String(format: "%.2f", self)
}
}
and call it like this :
let ex: Double = 10.123546789
print(ex.clean) // 10.12
Here's one for SwiftUI if you need a Text element with the number value.
struct RoundedDigitText : View {
let digits : Int
let number : Double
var body : some View {
Text(String(format: "%.\(digits)f", number))
}
}
//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"

Swift double to string

Before I updated xCode 6, I had no problems casting a double to a string but now it gives me an error
var a: Double = 1.5
var b: String = String(a)
It gives me the error message "double is not convertible to string". Is there any other way to do it?
It is not casting, it is creating a string from a value with a format.
let a: Double = 1.5
let b: String = String(format: "%f", a)
print("b: \(b)") // b: 1.500000
With a different format:
let c: String = String(format: "%.1f", a)
print("c: \(c)") // c: 1.5
You can also omit the format property if no formatting is needed.
let double = 1.5
let string = double.description
update Xcode 7.1 • Swift 2.1:
Now Double is also convertible to String so you can simply use it as you wish:
let double = 1.5
let doubleString = String(double) // "1.5"
Swift 3 or later we can extend LosslessStringConvertible and make it generic
Xcode 11.3 • Swift 5.1 or later
extension LosslessStringConvertible {
var string: String { .init(self) }
}
let double = 1.5
let string = double.string // "1.5"
For a fixed number of fraction digits we can extend FloatingPoint protocol:
extension FloatingPoint where Self: CVarArg {
func fixedFraction(digits: Int) -> String {
.init(format: "%.*f", digits, self)
}
}
If you need more control over your number format (minimum and maximum fraction digits and rounding mode) you can use NumberFormatter:
extension Formatter {
static let number = NumberFormatter()
}
extension FloatingPoint {
func fractionDigits(min: Int = 2, max: Int = 2, roundingMode: NumberFormatter.RoundingMode = .halfEven) -> String {
Formatter.number.minimumFractionDigits = min
Formatter.number.maximumFractionDigits = max
Formatter.number.roundingMode = roundingMode
Formatter.number.numberStyle = .decimal
return Formatter.number.string(for: self) ?? ""
}
}
2.12345.fractionDigits() // "2.12"
2.12345.fractionDigits(min: 3, max: 3, roundingMode: .up) // "2.124"
In addition to #Zaph's answer, you can create an extension on Double:
extension Double {
func toString() -> String {
return String(format: "%.1f",self)
}
}
Usage:
var a:Double = 1.5
println("output: \(a.toString())") // output: 1.5
Swift 3+: Try these line of code
let num: Double = 1.5
let str = String(format: "%.2f", num)
to make anything a string in swift except maybe enum values simply do what you do in the println() method
for example:
var stringOfDBL = "\(myDouble)"
There are many answers here that suggest a variety of techniques. But when presenting numbers in the UI, you invariably want to use a NumberFormatter so that the results are properly formatted, rounded, and localized:
let value = 10000.5
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
guard let string = formatter.string(for: value) else { return }
print(string) // 10,000.5
If you want fixed number of decimal places, e.g. for currency values
let value = 10000.5
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
formatter.maximumFractionDigits = 2
formatter.minimumFractionDigits = 2
guard let string = formatter.string(for: value) else { return }
print(string) // 10,000.50
But the beauty of this approach, is that it will be properly localized, resulting in 10,000.50 in the US but 10.000,50 in Germany. Different locales have different preferred formats for numbers, and we should let NumberFormatter use the format preferred by the end user when presenting numeric values within the UI.
Needless to say, while NumberFormatter is essential when preparing string representations within the UI, it should not be used if writing numeric values as strings for persistent storage, interface with web services, etc.
Swift 4:
Use following code
let number = 2.4
let string = String(format: "%.2f", number)
This function will let you specify the number of decimal places to show:
func doubleToString(number:Double, numberOfDecimalPlaces:Int) -> String {
return String(format:"%."+numberOfDecimalPlaces.description+"f", number)
}
Usage:
let numberString = doubleToStringDecimalPlacesWithDouble(number: x, numberOfDecimalPlaces: 2)
In swift 3:
var a: Double = 1.5
var b: String = String(a)
In swift 3 it is simple as given below
let stringDouble = String(describing: double)
I would prefer NSNumber and NumberFormatter approach (where need), also u can use extension to avoid bloating code
extension Double {
var toString: String {
return NSNumber(value: self).stringValue
}
}
U can also need reverse approach
extension String {
var toDouble: Double {
return Double(self) ?? .nan
}
}
var b = String(stringInterpolationSegment: a)
This works for me. You may have a try
In Swift 4 if you like to modify and use a Double in the UI as a textLabel "String" you can add this in the end of your file:
extension Double {
func roundToInt() -> Int{
return Int(Darwin.round(self))
}
}
And use it like this if you like to have it in a textlabel:
currentTemp.text = "\(weatherData.tempCelsius.roundToInt())"
Or print it as an Int:
print(weatherData.tempCelsius.roundToInt())
Swift 5:
Use following code
extension Double {
func getStringValue(withFloatingPoints points: Int = 0) -> String {
let valDouble = modf(self)
let fractionalVal = (valDouble.1)
if fractionalVal > 0 {
return String(format: "%.*f", points, self)
}
return String(format: "%.0f", self)
}
}
You shouldn't really ever cast a double to a string, the most common reason for casting a float to a string is to present it to a user, but floats are not real number and can only approximate lots of values, similar to how ⅓ can not be represented as a decimal number with a finite number of decimal places. Instead keep you values as float for all their use, then when you want to present them to the user, use something like NumberFormater to convert them for your. This stage of converting for user presentation is what something like your viewModel should do.
Use this.
Text(String(format: "%.2f", doubleValue))