450

Below is how I would have previously truncated a float to two decimal places

NSLog(@" %.02f %.02f %.02f", r, g, b);

I checked the docs and the eBook but haven't been able to figure it out. Thanks!

Brad Larson
  • 170,088
  • 45
  • 397
  • 571
user3524868
  • 4,513
  • 2
  • 12
  • 4

32 Answers32

881

The following code:

import Foundation // required for String(format: _, _)

print(String(format: "a float number: %.2f", 1.0321))

will output:

a float number: 1.03
Paulo Mattos
  • 18,845
  • 10
  • 77
  • 85
realityone
  • 13,542
  • 3
  • 13
  • 9
  • 9
    `println(String(format: "a float number: %.5f", 1.0321))` – zaph Jul 29 '14 at 03:31
  • 4
    This is better than the accepted answer but is still using Foundation methods (bridged to Swift). –  Jan 04 '15 at 17:16
  • FWIW I needed to convert a Float to 2 decimal places and used var valueAsString = String(format: "0.2f", value) and it worked without importing Foundation using Xcode 6.3 – Andrew H Jul 07 '15 at 13:15
  • Can also use `import Cocoa`. – RobG Mar 22 '18 at 01:07
  • surprising Swift doesn't seem to support native string formatting in print(). Although this might seem trivial, this type of solution has some efficiency concerns that it create a String object for doing such a trivial task. – galactica Feb 27 '19 at 00:08
  • @galactica you're saying that when you use string formatting in `printf()` it doesn't create a string? – Boris Verkhovskiy Dec 20 '21 at 15:49
313

My best solution so far, following from David's response:

import Foundation

extension Int {
    func format(f: String) -> String {
        return String(format: "%\(f)d", self)
    }
}

extension Double {
    func format(f: String) -> String {
        return String(format: "%\(f)f", self)
    }
}

let someInt = 4, someIntFormat = "03"
println("The integer number \(someInt) formatted with \"\(someIntFormat)\" looks like \(someInt.format(someIntFormat))")
// The integer number 4 formatted with "03" looks like 004

let someDouble = 3.14159265359, someDoubleFormat = ".3"
println("The floating point number \(someDouble) formatted with \"\(someDoubleFormat)\" looks like \(someDouble.format(someDoubleFormat))")
// The floating point number 3.14159265359 formatted with ".3" looks like 3.142

I think this is the most Swift-like solution, tying the formatting operations directly to the data type. It may well be that there is a built-in library of formatting operations somewhere, or maybe it will be released soon. Keep in mind that the language is still in beta.

Community
  • 1
  • 1
Anton Tcholakov
  • 3,710
  • 1
  • 12
  • 10
  • 85
    This is unnecessarily complicated. realityone's answer works and is much more concise. – Steven Marlowe Dec 20 '14 at 05:41
  • 11
    Sure if you are only using it once. But if you wanted to have more formatting options using string interpolation (which is much more readable) then you could put all the formatting extensions in a file elsewhere and reference it throughout your project. Of course, ideally Apple should provide the formatting library. – Anton Tcholakov Dec 20 '14 at 08:02
  • 2
    This solution won't work in Swift 1.2 without casting the result to String. – ibesora Apr 10 '15 at 06:32
  • Nice one, but not Swift 2 Friend. – LastMove Feb 29 '16 at 13:34
  • 5
    In SwiftUI use `Text("\(someDouble, specifier: "%.3f")")` – multitudes Oct 02 '20 at 15:51
133

I found String.localizedStringWithFormat to work quite well:

Example:

let value: Float = 0.33333
let unit: String = "mph"

yourUILabel.text = String.localizedStringWithFormat("%.2f %@", value, unit)
Valentin
  • 3,272
  • 1
  • 14
  • 22
  • The question has nothing to do with handling units. localizedStringWithFormat is nice , but not related. – AmitP Nov 14 '16 at 12:08
  • I agree AmitP, it was asked before String(format: ..., arguments: ...) was available – Valentin Nov 14 '16 at 12:11
98

This is a very fast and simple way who doesn't need complex solution.

let duration = String(format: "%.01f", 3.32323242)
// result = 3.3
fatihyildizhan
  • 8,614
  • 7
  • 64
  • 88
  • This doesn't compile (using 3.0.2 in IBM's Swift sandbox): `Col 16: 'init' has been renamed to 'init(describing:)'` – Peter Dillinger Jan 30 '17 at 16:35
  • @PeterDillinger you're passing an optional instead of unwrapped value. – Michael Feb 27 '18 at 11:37
  • This is a duplicate of [the answer](https://stackoverflow.com/a/24102844/20287183) posted 18 months earlier. – HangarRash Mar 07 '23 at 23:58
  • @HangarRash Hi, this answer posted 7 years ago. That post updated 4 times after I posted this answer. The original answer was totally different. The other one is duplicate. This one is the original. – fatihyildizhan Mar 08 '23 at 04:55
  • Yes, it's been updated over the years but the original version from 2014 (and the first two edits made before your answer) still showed how to use `String(format:)` so your answer didn't add any new information not already in that original answer. – HangarRash Mar 08 '23 at 05:01
  • @HangarRash They changed the original answer to almost the same as mine. There is nothing I can do to it. People have been using the answer I gave for 7 years. I contributed to the community. 97 people are also satisfied with this answer. I don't think there is a problem here. – fatihyildizhan Mar 08 '23 at 07:12
76

Most answers here are valid. However, in case you will format the number often, consider extending the Float class to add a method that returns a formatted string. See example code below. This one achieves the same goal by using a number formatter and extension.

extension Float {
    func string(fractionDigits:Int) -> String {
        let formatter = NSNumberFormatter()
        formatter.minimumFractionDigits = fractionDigits
        formatter.maximumFractionDigits = fractionDigits
        return formatter.stringFromNumber(self) ?? "\(self)"
    }
}

let myVelocity:Float = 12.32982342034

println("The velocity is \(myVelocity.string(2))")
println("The velocity is \(myVelocity.string(1))")

The console shows:

The velocity is 12.33
The velocity is 12.3

SWIFT 3.1 update

extension Float {
    func string(fractionDigits:Int) -> String {
        let formatter = NumberFormatter()
        formatter.minimumFractionDigits = fractionDigits
        formatter.maximumFractionDigits = fractionDigits
        return formatter.string(from: NSNumber(value: self)) ?? "\(self)"
    }
}
Efren
  • 4,003
  • 4
  • 33
  • 75
Donn
  • 1,680
  • 14
  • 17
  • 16
    I wish more people would use `NSNumberFormatter`, like this answer. The other highly-voted answers are simply failing to reflect device locale settings (e.g. in some locales, they use a comma for a decimal place; this reflects that; other answers do not). – Rob Mar 31 '15 at 12:56
  • 3
    The only improvement I'd like to see, is storing the formatter for any given number - the NSNumberFormatters are expensive to construct. – Kendall Helmstetter Gelner Apr 02 '15 at 07:04
  • 1
    exactly, what i was looking for! Thanks – gunjot singh Nov 19 '16 at 11:00
  • 1
    I know this is a somewhat old question, but `NSNumberFormatter` is fairly slow to initialize. If possible, it helps to define one and reuse it. That said, I'm here reading this question because that's not possible in my case. – promacuser Jun 22 '17 at 13:35
53

You can't do it (yet) with string interpolation. Your best bet is still going to be NSString formatting:

println(NSString(format:"%.2f", sqrt(2.0)))

Extrapolating from python, it seems like a reasonable syntax might be:

@infix func % (value:Double, format:String) -> String {
    return NSString(format:format, value)
}

Which then allows you to use them as:

M_PI % "%5.3f"                // "3.142"

You can define similar operators for all of the numeric types, unfortunately I haven't found a way to do it with generics.

Swift 5 Update

As of at least Swift 5, String directly supports the format: initializer, so there's no need to use NSString and the @infix attribute is no longer needed which means the samples above should be written as:

println(String(format:"%.2f", sqrt(2.0)))

func %(value:Double, format:String) -> String {
    return String(format:format, value)
}

Double.pi % "%5.3f"         // "3.142"
David Berry
  • 40,941
  • 12
  • 84
  • 95
  • where did you find that syntax `NSString(format: "formatString", val)'. I don't see it in the iBooks document from Apple. – Duncan C Jun 05 '14 at 14:51
  • 1
    It's the same as constructing any objective-c object from swift. It's the swift version of `[NSString stringWithFormat...` – David Berry Jun 05 '14 at 15:25
  • Gotcha. I haven't gotten that far in the Swift iBook yet. – Duncan C Jun 05 '14 at 20:46
  • IIRC that wasn't in the Swift iBook. It was in one of the WWDC sessions. [Swift Interoperability In Depth](https://developer.apple.com/videos/wwdc/2014/#407-video) – ahruss Jun 08 '14 at 07:33
  • @David, see my reply, that might interest you ;) – Vincent Guerci Jun 14 '14 at 11:23
  • @VincentGuerci actually I have another question somewhere that I answer with a global solution to the % option. See the question and my answer [here](http://stackoverflow.com/questions/24210720/generic-protocol-for-basic-types/24213938#24213938) – David Berry Jun 14 '14 at 16:14
  • 2
    If you were implementing % as in Python it should be the other way around. "%5.3f" % M_PI – Andy Dent Jun 19 '14 at 02:47
  • @AndyDent good point. Good thing I'm not to stuck on semantics :) – David Berry Jun 19 '14 at 05:08
17

Why make it so complicated? You can use this instead:

import UIKit

let PI = 3.14159265359

round( PI ) // 3.0 rounded to the nearest decimal
round( PI * 100 ) / 100 //3.14 rounded to the nearest hundredth
round( PI * 1000 ) / 1000 // 3.142 rounded to the nearest thousandth

See it work in Playground.

PS: Solution from: http://rrike.sh/xcode/rounding-various-decimal-places-swift/

Steyn Viljoen
  • 327
  • 2
  • 7
15
import Foundation

extension CGFloat {
    var string1: String {
        return String(format: "%.1f", self)
    }
    var string2: String {
        return String(format: "%.2f", self)
    }
}

Usage

let offset = CGPoint(1.23, 4.56)
print("offset: \(offset.x.string1) x \(offset.y.string1)")
// offset: 1.2 x 4.6
neoneye
  • 50,398
  • 25
  • 166
  • 151
14

After iOS 15+ this solution is recommended:

2.31234.formatted(.number.precision(.fractionLength(1)))
Marcy
  • 4,611
  • 2
  • 34
  • 52
Tiago Almeida
  • 14,081
  • 3
  • 67
  • 82
11

A more elegant and generic solution is to rewrite ruby / python % operator:

// Updated for beta 5
func %(format:String, args:[CVarArgType]) -> String {
    return NSString(format:format, arguments:getVaList(args))
}

"Hello %@, This is pi : %.2f" % ["World", M_PI]
mmmmmm
  • 32,227
  • 27
  • 88
  • 117
Vincent Guerci
  • 14,379
  • 4
  • 50
  • 56
  • Sadly this dies in beta 6: fatal error: can't unsafeBitCast between types of different sizes. – binarymochi Aug 22 '14 at 08:15
  • @binarymochi With Beta 6: `"Hello %@, This is pi : %.2f" % ["World", M_PI]` does work, but strangely `"%@ %@" % ["Hello", "World"]` raise `can't unsafeBitCast`... Guess that will be fixed in next version. – Vincent Guerci Aug 22 '14 at 09:23
  • Could you make ',' into the operator used? '@infix func ,(…', and then write your strings like "Hello %@, this is pi: %.2f", ["you", M_PI])? – Rick Oct 19 '14 at 02:09
  • @Rick no you can't, `,` is not a valid character operator, in Swift and most languages. And imo, it's better to use `%` operator that already exists in other languages. See https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/doc/uid/TP40014097-CH30-XID_955 – Vincent Guerci Oct 23 '14 at 12:34
9

Details

  • Xcode 9.3, Swift 4.1
  • Xcode 10.2.1 (10E1001), Swift 5

Solution 1

func rounded() -> Double

(5.2).rounded()
// 5.0
(5.5).rounded()
// 6.0
(-5.2).rounded()
// -5.0
(-5.5).rounded()
// -6.0

func rounded(_ rule: FloatingPointRoundingRule) -> Double

let x = 6.5

// Equivalent to the C 'round' function:
print(x.rounded(.toNearestOrAwayFromZero))
// Prints "7.0"

// Equivalent to the C 'trunc' function:
print(x.rounded(.towardZero))
// Prints "6.0"

// Equivalent to the C 'ceil' function:
print(x.rounded(.up))
// Prints "7.0"

// Equivalent to the C 'floor' function:
print(x.rounded(.down))
// Prints "6.0"

mutating func round()

var x = 5.2
x.round()
// x == 5.0
var y = 5.5
y.round()
// y == 6.0
var z = -5.5
z.round()
// z == -6.0

mutating func round(_ rule: FloatingPointRoundingRule)

// Equivalent to the C 'round' function:
var w = 6.5
w.round(.toNearestOrAwayFromZero)
// w == 7.0

// Equivalent to the C 'trunc' function:
var x = 6.5
x.round(.towardZero)
// x == 6.0

// Equivalent to the C 'ceil' function:
var y = 6.5
y.round(.up)
// y == 7.0

// Equivalent to the C 'floor' function:
var z = 6.5
z.round(.down)
// z == 6.0

Solution 2

extension Numeric {

    private func _precision(number: NSNumber, formatter: NumberFormatter) -> Self? {
        if  let formatedNumString = formatter.string(from: number),
            let formatedNum = formatter.number(from: formatedNumString) {
                return formatedNum as? Self
        }
        return nil
    }

    private func toNSNumber() -> NSNumber? {
        if let num = self as? NSNumber { return num }
        guard let string = self as? String, let double = Double(string) else { return nil }
        return NSNumber(value: double)
    }

    func precision(_ minimumFractionDigits: Int,
                   roundingMode: NumberFormatter.RoundingMode = NumberFormatter.RoundingMode.halfUp) -> Self? {
        guard let number = toNSNumber() else { return nil }
        let formatter = NumberFormatter()
        formatter.minimumFractionDigits = minimumFractionDigits
        formatter.roundingMode = roundingMode
        return _precision(number: number, formatter: formatter)
    }

    func precision(with numberFormatter: NumberFormatter) -> String? {
        guard let number = toNSNumber() else { return nil }
        return numberFormatter.string(from: number)
    }
}

Usage

_ = 123.44.precision(2)
_ = 123.44.precision(3, roundingMode: .up)

let numberFormatter = NumberFormatter()
numberFormatter.minimumFractionDigits = 1
numberFormatter.groupingSeparator = " "
let num = 222.3333
_ = num.precision(2)

Full sample

func option1<T: Numeric>(value: T, numerFormatter: NumberFormatter? = nil) {
    print("Type: \(type(of: value))")
    print("Original Value: \(value)")
    let value1 = value.precision(2)
    print("value1 = \(value1 != nil ? "\(value1!)" : "nil")")
    let value2 = value.precision(5)
    print("value2 = \(value2 != nil ? "\(value2!)" : "nil")")
    if let value1 = value1, let value2 = value2 {
        print("value1 + value2 = \(value1 + value2)")
    }
    print("")
}

func option2<T: Numeric>(value: T, numberFormatter: NumberFormatter) {
    print("Type: \(type(of: value))")
    print("Original Value: \(value)")
    let value1 = value.precision(with: numberFormatter)
    print("formated value = \(value1 != nil ? "\(value1!)" : "nil")\n")
}

func test(with double: Double) {
    print("===========================\nTest with: \(double)\n")
    let float = Float(double)
    let float32 = Float32(double)
    let float64 = Float64(double)
    let float80 = Float80(double)
    let cgfloat = CGFloat(double)

    // Exapmle 1
    print("-- Option1\n")
    option1(value: double)
    option1(value: float)
    option1(value: float32)
    option1(value: float64)
    option1(value: float80)
    option1(value: cgfloat)

    // Exapmle 2

    let numberFormatter = NumberFormatter()
    numberFormatter.formatterBehavior = .behavior10_4
    numberFormatter.minimumIntegerDigits = 1
    numberFormatter.minimumFractionDigits = 4
    numberFormatter.maximumFractionDigits = 9
    numberFormatter.usesGroupingSeparator = true
    numberFormatter.groupingSeparator = " "
    numberFormatter.groupingSize = 3

    print("-- Option 2\n")
    option2(value: double, numberFormatter: numberFormatter)
    option2(value: float, numberFormatter: numberFormatter)
    option2(value: float32, numberFormatter: numberFormatter)
    option2(value: float64, numberFormatter: numberFormatter)
    option2(value: float80, numberFormatter: numberFormatter)
    option2(value: cgfloat, numberFormatter: numberFormatter)
}

test(with: 123.22)
test(with: 1234567890987654321.0987654321)

Output

===========================
Test with: 123.22

-- Option1

Type: Double
Original Value: 123.22
value1 = 123.22
value2 = 123.22
value1 + value2 = 246.44

Type: Float
Original Value: 123.22
value1 = nil
value2 = nil

Type: Float
Original Value: 123.22
value1 = nil
value2 = nil

Type: Double
Original Value: 123.22
value1 = 123.22
value2 = 123.22
value1 + value2 = 246.44

Type: Float80
Original Value: 123.21999999999999886
value1 = nil
value2 = nil

Type: CGFloat
Original Value: 123.22
value1 = 123.22
value2 = 123.22
value1 + value2 = 246.44

-- Option 2

Type: Double
Original Value: 123.22
formatted value = 123.2200

Type: Float
Original Value: 123.22
formatted value = 123.220001221

Type: Float
Original Value: 123.22
formatted value = 123.220001221

Type: Double
Original Value: 123.22
formatted value = 123.2200

Type: Float80
Original Value: 123.21999999999999886
formatted value = nil

Type: CGFloat
Original Value: 123.22
formatted value = 123.2200

===========================
Test with: 1.2345678909876544e+18

-- Option1

Type: Double
Original Value: 1.2345678909876544e+18
value1 = 1.23456789098765e+18
value2 = 1.23456789098765e+18
value1 + value2 = 2.4691357819753e+18

Type: Float
Original Value: 1.234568e+18
value1 = nil
value2 = nil

Type: Float
Original Value: 1.234568e+18
value1 = nil
value2 = nil

Type: Double
Original Value: 1.2345678909876544e+18
value1 = 1.23456789098765e+18
value2 = 1.23456789098765e+18
value1 + value2 = 2.4691357819753e+18

Type: Float80
Original Value: 1234567890987654400.0
value1 = nil
value2 = nil

Type: CGFloat
Original Value: 1.2345678909876544e+18
value1 = 1.23456789098765e+18
value2 = 1.23456789098765e+18
value1 + value2 = 2.4691357819753e+18

-- Option 2

Type: Double
Original Value: 1.2345678909876544e+18
formatted value = 1 234 567 890 987 650 000.0000

Type: Float
Original Value: 1.234568e+18
formatted value = 1 234 567 939 550 610 000.0000

Type: Float
Original Value: 1.234568e+18
formatted value = 1 234 567 939 550 610 000.0000

Type: Double
Original Value: 1.2345678909876544e+18
formatted value = 1 234 567 890 987 650 000.0000

Type: Float80
Original Value: 1234567890987654400.0
formatted value = nil

Type: CGFloat
Original Value: 1.2345678909876544e+18
formatted value = 1 234 567 890 987 650 000.0000
Vasily Bodnarchuk
  • 24,482
  • 9
  • 132
  • 127
8

Swift 4

let string = String(format: "%.2f", locale: Locale.current, arguments: 15.123)
onmyway133
  • 45,645
  • 31
  • 257
  • 263
6

You can still use NSLog in Swift as in Objective-C just without the @ sign.

NSLog("%.02f %.02f %.02f", r, g, b)

Edit: After working with Swift since a while I would like to add also this variation

    var r=1.2
    var g=1.3
    var b=1.4
    NSLog("\(r) \(g) \(b)")

Output:

2014-12-07 21:00:42.128 MyApp[1626:60b] 1.2 1.3 1.4
hol
  • 8,255
  • 5
  • 33
  • 59
5
extension Double {
  func formatWithDecimalPlaces(decimalPlaces: Int) -> Double {
     let formattedString = NSString(format: "%.\(decimalPlaces)f", self) as String
     return Double(formattedString)!
     }
 }

 1.3333.formatWithDecimalPlaces(2)
Lucas Farah
  • 1,022
  • 10
  • 24
3

The answers given so far that have received the most votes are relying on NSString methods and are going to require that you have imported Foundation.

Having done that, though, you still have access to NSLog.

So I think the answer to the question, if you are asking how to continue using NSLog in Swift, is simply:

import Foundation

fqdn
  • 2,823
  • 1
  • 13
  • 16
3
//It will more help, by specify how much decimal Point you want.
let decimalPoint = 2
let floatAmount = 1.10001
let amountValue = String(format: "%0.*f", decimalPoint, floatAmount)
Ravi Kumar
  • 1,356
  • 14
  • 22
2

here a "pure" swift solution

 var d = 1.234567
operator infix ~> {}
@infix func ~> (left: Double, right: Int) -> String {
    if right == 0 {
        return "\(Int(left))"
    }
    var k = 1.0
    for i in 1..right+1 {
        k = 10.0 * k
    }
    let n = Double(Int(left*k)) / Double(k)
    return "\(n)"
}
println("\(d~>2)")
println("\(d~>1)")
println("\(d~>0)")
Christian Dietrich
  • 11,778
  • 4
  • 24
  • 32
2

Power of extension

extension Double {
    var asNumber:String {
        if self >= 0 {
            var formatter = NSNumberFormatter()
            formatter.numberStyle = .NoStyle
            formatter.percentSymbol = ""
            formatter.maximumFractionDigits = 1
            return "\(formatter.stringFromNumber(self)!)"
        }
        return ""
    }
}

let velocity:Float = 12.32982342034

println("The velocity is \(velocity.toNumber)")

Output: The velocity is 12.3

Muhammad Aamir Ali
  • 20,419
  • 10
  • 66
  • 57
2

less typing way:

func fprint(format: String, _ args: CVarArgType...) {
    print(NSString(format: format, arguments: getVaList(args)))
}
peak
  • 311
  • 3
  • 6
2

Plenty of good answers above, but sometimes a pattern is more appropriate than the "%.3f" sort of gobbledygook. Here's my take using a NumberFormatter in Swift 3.

extension Double {
  func format(_ pattern: String) -> String {
    let formatter = NumberFormatter()
    formatter.format = pattern
    return formatter.string(from: NSNumber(value: self))!
  }    
}

let n1 = 0.350, n2 = 0.355
print(n1.format("0.00#")) // 0.35
print(n2.format("0.00#")) // 0.355

Here I wanted 2 decimals to be always shown, but the third only if it wasn't zero.

AlexT
  • 596
  • 7
  • 15
2

What about extensions on Double and CGFloat types:

extension Double {

   func formatted(_ decimalPlaces: Int?) -> String {
      let theDecimalPlaces : Int
      if decimalPlaces != nil {
         theDecimalPlaces = decimalPlaces!
      }
      else {
         theDecimalPlaces = 2
      }
      let theNumberFormatter = NumberFormatter()
      theNumberFormatter.formatterBehavior = .behavior10_4
      theNumberFormatter.minimumIntegerDigits = 1
      theNumberFormatter.minimumFractionDigits = 1
      theNumberFormatter.maximumFractionDigits = theDecimalPlaces
      theNumberFormatter.usesGroupingSeparator = true
      theNumberFormatter.groupingSeparator = " "
      theNumberFormatter.groupingSize = 3

      if let theResult = theNumberFormatter.string(from: NSNumber(value:self)) {
         return theResult
      }
      else {
         return "\(self)"
      }
   }
}

Usage:

let aNumber: Double = 112465848348508.458758344
Swift.print("The number: \(aNumber.formatted(2))")

prints: 112 465 848 348 508.46

M Wilm
  • 184
  • 7
1

You can also create an operator in this way

operator infix <- {}

func <- (format: String, args:[CVarArg]) -> String {
    return String(format: format, arguments: args)
}

let str = "%d %.1f" <- [1453, 1.123]
otello
  • 29
  • 2
1

Also with rounding:

extension Float
{
    func format(f: String) -> String
    {
        return NSString(format: "%\(f)f", self)
    }
    mutating func roundTo(f: String)
    {
        self = NSString(format: "%\(f)f", self).floatValue
    }
}

extension Double
{
    func format(f: String) -> String
    {
        return NSString(format: "%\(f)f", self)
    }
    mutating func roundTo(f: String)
    {
        self = NSString(format: "%\(f)f", self).doubleValue
    }
}

x = 0.90695652173913
x.roundTo(".2")
println(x) //0.91
ChikabuZ
  • 10,031
  • 5
  • 63
  • 86
1

use below method

let output = String.localizedStringWithFormat(" %.02f %.02f %.02f", r, g, b)

println(output)
Robert
  • 5,278
  • 43
  • 65
  • 115
Ramkumar chintala
  • 958
  • 11
  • 24
1

A version of Vincent Guerci's ruby / python % operator, updated for Swift 2.1:

func %(format:String, args:[CVarArgType]) -> String {
  return String(format:format, arguments:args)
}

"Hello %@, This is pi : %.2f" % ["World", M_PI]
Paul King
  • 1,881
  • 20
  • 23
1

Swift 4 Xcode 10 Update

extension Double {
    var asNumber:String {
        if self >= 0 {
            let formatter = NumberFormatter()
            formatter.numberStyle = .none
            formatter.percentSymbol = ""
            formatter.maximumFractionDigits = 2
            return "\(formatter.string(from: NSNumber(value: self)) ?? "")"
        }
        return ""
    }
}
Leanid Vouk
  • 460
  • 6
  • 13
0
@infix func ^(left:Double, right: Int) -> NSNumber {
    let nf = NSNumberFormatter()
    nf.maximumSignificantDigits = Int(right)
    return  nf.numberFromString(nf.stringFromNumber(left))
}


let r = 0.52264
let g = 0.22643
let b = 0.94837

println("this is a color: \(r^3) \(g^3) \(b^3)")

// this is a color: 0.523 0.226 0.948
0

I don't know about two decimal places, but here's how you can print floats with zero decimal places, so I'd imagine that can be 2 place, 3, places ... (Note: you must convert CGFloat to Double to pass to String(format:) or it will see a value of zero)

func logRect(r: CGRect, _ title: String = "") {
    println(String(format: "[ (%.0f, %.0f), (%.0f, %.0f) ] %@",
        Double(r.origin.x), Double(r.origin.y), Double(r.size.width), Double(r.size.height), title))
}
clearlight
  • 12,255
  • 11
  • 57
  • 75
0

Swift2 example: Screen width of iOS device formatting the Float removing the decimal

print(NSString(format: "Screen width = %.0f pixels", CGRectGetWidth(self.view.frame)))
0

If suggestion to add SwiftUI’s LocalizedStringKey.appendInterpolation methods to DefaultStringInterpolation is adopted there will be an option to write:

print("\(someValue, specifier: "%0.2f")")

If this The Swift Evolution proposal, SE-0228 is adopted it will be possible to write:

// Use printf-style format strings:
"The price is $\(cost, format: "%.2f")"

// Use UTS #35 number formats:
"The price is \(cost, format: "¤###,##0.00")"

// Use Foundation.NumberFormatter, or a new type-safe native formatter:
"The price is \(cost, format: moneyFormatter)"

// Mimic String.init(_:radix:uppercase:)
"The checksum is 0x\(checksum, radix: 16)"

Meanwhile you can set your interpolation rules by extending StringInterpolation protocol:

extension String.StringInterpolation {
    mutating func appendInterpolation<T: BinaryFloatingPoint>(_ value: T, using style: NumberFormatter.Style, maxFractionDigits: Int? = nil)  {
        let formatter = NumberFormatter()
        formatter.numberStyle = style
        if let maxFractionDigits {
            formatter.maximumFractionDigits = maxFractionDigits
        }
        
        if let value = value as? NSNumber, let result = formatter.string(from: value as NSNumber) {
            appendLiteral(result)
        }
    }
}

Then it becomes possible to write:

print("The value is \(123.456, using: .decimal, maxFractionDigits: 2).")
// The value is 123.46.

Or we can do something like this:

extension String.StringInterpolation {
    mutating func appendInterpolation(_ value: Double, formatted style: FloatingPointFormatStyle<Double>)  {
        appendLiteral(value.formatted(style))
    }
}

print("The value is \(123.456, formatted: .number.precision(.fractionLength(1)))")
// The value is 123.5
Paul B
  • 3,989
  • 33
  • 46
-1

@Christian Dietrich:

instead of:

var k = 1.0
    for i in 1...right+1 {
        k = 10.0 * k
    }
let n = Double(Int(left*k)) / Double(k)
return "\(n)"

it could also be:

let k = pow(10.0, Double(right))
let n = Double(Int(left*k)) / k
return "\(n)"

[correction:] Sorry for confusion* - Of course this works with Doubles. I think, most practical (if you want digits to be rounded, not cut off) it would be something like that:

infix operator ~> {}
func ~> (left: Double, right: Int) -> Double {
    if right <= 0 {
        return round(left)
    }
    let k = pow(10.0, Double(right))
    return round(left*k) / k
}

For Float only, simply replace Double with Float, pow with powf and round with roundf.
Update: I found that it is most practical to use return type Double instead of String. It works the same for String output, i.e.:

println("Pi is roughly \(3.1415926 ~> 3)")

prints: Pi is roughly 3.142
So you can use it the same way for Strings (you can even still write: println(d ~> 2)), but additionally you can also use it to round values directly, i.e.:

d = Double(slider.value) ~> 2

or whatever you need …

  • This is obviously intended to be a comment, I understand that you need more space to make a point, and it's valuable, but if you're going to write it as a full-fledged answer make it useful by itself, independently; you could add the full code, for example, and then a remark and acknowledge to Christian. – Jaime Gómez Feb 23 '15 at 00:10
  • @Jaime Gómez: I am not allowed to comment the above answer. But anyway, I had some false interpretation* in it. Don't know, if it's worth being kept or should be deleted. Of course this can be used in a similar way just for rounding (w/o String conversion) and can easily translated to other programming languages. _*I assumed that with Double it gets rounded to about 8 digits, which of course was an error, because I did round it with Float and converted that to Double accidentely._ – Stuepfnick Feb 23 '15 at 08:28
  • PS: I would prefer to use similar methods more for rounding in general, not String output, so return type Double (& regular method?) **Sidenote**: If you round a Float that way (i.e. from a Slider) and the result to String it will be fine, like "0.1", but if you convert that Float to Double and then to String* it will be: "0.100000001490116", as Float is not capable of storing 0.1 exactly, only very close. I guess it's the same with Double, just with _double precision_ ;) So _always_ convert to Double _before_ rounding, so it will be as exact as possible and converts to String fine too. – Stuepfnick Mar 02 '15 at 00:10
  • PPS: Of course, with Return Type Double, it's a little different sometimes, i.e. if you need to set a label text, you need to write: _myLabel.text = "\\(d ~> 2)"_ instead of just: _myLabel.text = d ~> 2_ , but I still think, the function is more practical that way. (of course everybody can do, what they want, just my thoughts …) – Stuepfnick Mar 07 '15 at 02:45
-2

use

CGFloat 

or

Float.roundTo(places:2)
Nicson
  • 9
  • 4