Swift specify double without converting to string - swift

I want to specify my (slider) double to 2 decimals but xcode won't let me do that:
return (Double(pris, specifier: "%.2f"))
And i don't want to convert it into a string and then format it because numbers like 600000000 are then unreadable.
I have tried solutions like :
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
}
}

let b: Double = Double(600000000.376)
let result = Double(round(100*b)/100)
print(result) // prints 600000000.38

This should do what you need:
extension Double {
func roundedTo(places: Int) -> Double {
let conversion = pow(10.0, Double(places))
return (self * conversion).rounded() / conversion
}
}
print(10.125.roundedTo(places: 2)) // prints 10.13
print(10.124.roundedTo(places: 2)) // prints 10.12

The simple solution was to remove the (Double) before the calculation.
return (Double(pris, specifier: "%.2f"))
should be only
pris, specifier: "%.2f")

Related

How can you create a generic struct for Numeric numbers that can calculate a percentage?

This doesn't compile because Initializer 'init(_:)' requires that 'Number' conform to 'BinaryInteger'
struct Percentage<Number: Numeric> {
let value: Number
let total: Number
var percentage: Double {
Double(value) / Double(total)
}
}
Does anyone have a nice solution?
To give some context to the problem from real life: I'm coding a SwiftUI app, that has a CircularProgress-view. I would like to use the same CircularProgress-view with different number types and to be able to show the current value in proportion to min and max. To do that, I need to solve the problem above.
The main issue is that Numeric doesn't support generic divisions. One possible solution is to provide multiple generic methods to support different protocols (Integer/FloatingPoint) and Decimal as well:
extension Decimal {
var number: NSDecimalNumber { self as NSDecimalNumber }
var double: Double { number.doubleValue }
}
struct Percentage<T: Numeric> {
let value: T
let total: T
func percentage<F: BinaryFloatingPoint>() -> F where T: BinaryFloatingPoint {
F(value) / F(total)
}
func percentage<F: BinaryFloatingPoint>() -> F where T: BinaryInteger {
F(value) / F(total)
}
func percentage<F: BinaryFloatingPoint>() -> F where T == Decimal {
F(value.double) / F(total.double)
}
func percentage() -> Decimal where T == Decimal {
value / total
}
}
let percentageInt = Percentage<Int>(value: 10, total: 100)
let result1: Double = percentageInt.percentage() // 0.1
let percentageDouble = Percentage<Double>(value: 10, total: 100)
let result2: Double = percentageDouble.percentage() // 0.1
let result3: CGFloat = percentageDouble.percentage() // 0.1
let percentageDecimal = Percentage<Decimal>(value: 10, total: 100)
let result4 = percentageDecimal.percentage() // 0.1 decimal
let result5: Double = percentageDecimal.percentage() // 0.1
You can create extensions on Percentage where you restrict Number to BinaryInteger and FloatingPoint to be able to use the / operator.
struct Percentage<Number: Numeric> {
let value: Number
let total: Number
}
extension Percentage where Number: BinaryInteger {
var percentage: Double {
Double(value) / Double(total)
}
}
extension Percentage where Number: FloatingPoint {
var percentage: Number {
value / total
}
}
Percentage(value: 15, total: 60).percentage // 25.0
Percentage(value: 1.5, total: 3.0).percentage // 50.0

Convert a Double to Hex notation in Swift

How do I convert a very large number into hex?
For example, 647751843213568900000 in hex is 0x231d5cd577654ceab3. I'm able to easily go from hex to double with:
let hex: Double = 0x231d5cd577654ceab3
However I can't work out how to go from Double back to hex. What am I missing?
The following does not work as it overflows when stored as an 'Int':
let hexConverted = String(647751843213568900000, radix: 16)
The basic algorithm (Swift 5) is the following:
func representationOf<T: FixedWidthInteger>(_ number: T, base: T) -> String {
var buffer: [Int] = []
var n = number
while n > 0 {
buffer.append(Int(n % base))
n /= base
}
return buffer
.reversed()
.map { String($0, radix: Int(base)) }
.joined()
}
print(representationOf(647751843213568900, base: 16))
Of course, this is what String(_:radix:) is doing so there is no need for us to implement it by ourselves.
Your real problem is not the encoding but the representation of big integers.
There are multiple implementations out there already, for example https://github.com/mkrd/Swift-Big-Integer. Some of them already have functions for hex encoding.
In Swift 4 it will be possible to declare your own implementation of higher IntXXX (conforming to FixedWidthInteger) and the problem will become a bit easier:
typealias Int128 = DoubleWidth<Int64>
typealias Int256 = DoubleWidth<Int128>
let longNumber = Int256("231d5cd577654ceab3", radix: 16)!
print(longNumber)
print(String(longNumber, radix: 16))
But unfortunately, the DoubleWidth is not implemented in Xcode 9 Beta 4 yet.
For some values your can also use the Decimal type. Using the algorithm written above:
extension Decimal {
func rounded(mode: NSDecimalNumber.RoundingMode) -> Decimal {
var this = self
var result = Decimal()
NSDecimalRound(&result, &this, 0, mode)
return result
}
func integerDivisionBy(_ operand: Decimal) -> Decimal{
let result = (self / operand)
return result.rounded(mode: result < 0 ? .up : .down)
}
func truncatingRemainder(dividingBy operand: Decimal) -> Decimal {
return self - self.integerDivisionBy(operand) * operand
}
}
extension Decimal {
init(_ string: String, base: Int) {
var decimal: Decimal = 0
let digits = Array(string)
.map { String($0) }
.map { Int($0, radix: base)! }
for digit in digits {
decimal *= Decimal(base)
decimal += Decimal(digit)
}
self.init(string: decimal.description)!
}
}
func representationOf(_ number: Decimal, base: Decimal) -> String {
var buffer: [Int] = []
var n = number
while n > 0 {
buffer.append((n.truncatingRemainder(dividingBy: base) as NSDecimalNumber).intValue)
n = n.integerDivisionBy(base)
}
return buffer
.reversed()
.map { String($0, radix: (base as NSDecimalNumber).intValue ) }
.joined()
}
let number = Decimal("231d5cd577654ceab3", base: 16)
print(number) // 647751843213568961203
print(representationOf(number, base: 16)) // 231d5cd577654ceab3
Note how your value got truncated when converted to Double.
here is my solution :
func toHex(number : Double) -> String
{
var n = number;
var reminders : [Double] = [];
while true
{
let reminder = n % 16;
n = floor(n/16.0);
reminders.append(reminder);
if(n == 0.0)
{
break;
}
}
var hex = "";
var i = reminders.count-1;
while(i > -1)
{
hex = hex + hexChar(reminders[i]);
i = i-1;
}
return hex;
}
func hexChar(n : Double) -> String
{
switch n
{
case 15: return "F";
case 14: return "E";
case 13: return "D";
case 12: return "C";
case 11: return "B";
case 10: return "A";
default: return String(Int(n))
}
}
toHex(647751843213568900000.0); //231D5CD577654C0000

Round Double to closest 10

I would like to round a Double to the closest multiple of 10.
For example if the number is 8.0 then round to 10.
If the number is 2.0 round it to 0.
How can I do that?
You can use the round() function (which rounds a floating point number
to the nearest integral value) and apply a "scale factor" of 10:
func roundToTens(x : Double) -> Int {
return 10 * Int(round(x / 10.0))
}
Example usage:
print(roundToTens(4.9)) // 0
print(roundToTens(15.1)) // 20
In the second example, 15.1 is divided by ten (1.51), rounded (2.0),
converted to an integer (2) and multiplied by 10 again (20).
Swift 3:
func roundToTens(_ x : Double) -> Int {
return 10 * Int((x / 10.0).rounded())
}
Alternatively:
func roundToTens(_ x : Double) -> Int {
return 10 * lrint(x / 10.0)
}
defining the rounding function as
import Foundation
func round(_ value: Double, toNearest: Double) -> Double {
return round(value / toNearest) * toNearest
}
gives you more general and flexible way how to do it
let r0 = round(1.27, toNearest: 0.25) // 1.25
let r1 = round(325, toNearest: 10) // 330.0
let r3 = round(.pi, toNearest: 0.0001) // 3.1416
UPDATE
more generic definitions
func round<T:BinaryFloatingPoint>(_ value:T, toNearest:T) -> T {
return round(value / toNearest) * toNearest
}
func round<T:BinaryInteger>(_ value:T, toNearest:T) -> T {
return T(round(Double(value), toNearest:Double(toNearest)))
}
and usage
let A = round(-13.16, toNearest: 0.25)
let B = round(8, toNearest: 3.0)
let C = round(8, toNearest: 5)
print(A, type(of: A))
print(B, type(of: B))
print(C, type(of: C))
prints
-13.25 Double
9.0 Double
10 Int
You can also extend FloatingPoint protocol and add an option to choose the rounding rule:
extension FloatingPoint {
func rounded(to value: Self, roundingRule: FloatingPointRoundingRule = .toNearestOrAwayFromZero) -> Self {
(self / value).rounded(roundingRule) * value
}
}
let value = 325.0
value.rounded(to: 10) // 330 (default rounding mode toNearestOrAwayFromZero)
value.rounded(to: 10, roundingRule: .down) // 320
In Swift 3.0 it is
10 * Int(round(Double(ratio / 10)))
Extension for rounding to any number !
extension Int{
func rounding(nearest:Float) -> Int{
return Int(nearest * round(Float(self)/nearest))
}
}
Nice extension for BinaryFloatingPoint in swift:
extension BinaryFloatingPoint{
func roundToTens() -> Int{
return 10 * Int(Darwin.round(self / 10.0))
}
func roundToHundreds() -> Int{
return 100 * Int(Darwin.round(self / 100.0))
}
}
extension Double {
var roundToTens: Double {
let divideByTen = self / 10
let multiByTen = (ceil(divideByTen) * 10)
return multiByTen
}
}
usage:
36. roundToTens

How to convert a decimal number to binary in Swift?

How can I convert Int to UInt8 in Swift?
Example. I want to convert number 22 to 0b00010110
var decimal = 22
var binary:UInt8 = ??? //What should I write here?
You can convert the decimal value to a human-readable binary representation using the String initializer that takes a radix parameter:
let num = 22
let str = String(num, radix: 2)
print(str) // prints "10110"
If you wanted to, you could also pad it with any number of zeroes pretty easily as well:
Swift 5
func pad(string : String, toSize: Int) -> String {
var padded = string
for _ in 0..<(toSize - string.count) {
padded = "0" + padded
}
return padded
}
let num = 22
let str = String(num, radix: 2)
print(str) // 10110
pad(string: str, toSize: 8) // 00010110
Swift 5.1 / Xcode 11
Thanks Gustavo Seidler.
My version of his solution is complemented by spaces for readability.
extension BinaryInteger {
var binaryDescription: String {
var binaryString = ""
var internalNumber = self
var counter = 0
for _ in (1...self.bitWidth) {
binaryString.insert(contentsOf: "\(internalNumber & 1)", at: binaryString.startIndex)
internalNumber >>= 1
counter += 1
if counter % 4 == 0 {
binaryString.insert(contentsOf: " ", at: binaryString.startIndex)
}
}
return binaryString
}
}
Examples:
UInt8(9).binaryDescription // "0000 1001"
Int8(5).binaryDescription // "0000 0101"
UInt16(1945).binaryDescription // "0000 0111 1001 1001"
Int16(14).binaryDescription // "0000 0000 0000 1110"
Int32(6).binaryDescription // "0000 0000 0000 0000 0000 0000 0000 0110"
UInt32(2018).binaryDescription // "0000 0000 0000 0000 0000 0111 1110 0010"
I modified someone's version to swift 3.0 used the correct initializer for creating a string with repeated values
extension String {
func pad(with character: String, toLength length: Int) -> String {
let padCount = length - self.characters.count
guard padCount > 0 else { return self }
return String(repeating: character, count: padCount) + self
}
}
String(37, radix: 2).pad(with: "0", toLength: 8) // "00100101"
Since none of the solutions contemplate negative numbers, I came up with a simple solution that basically reads the number's internal representation and pads it automatically to the width of its type. This should work on all BinaryInteger types.
extension BinaryInteger {
var binaryDescription: String {
var binaryString = ""
var internalNumber = self
for _ in (1...self.bitWidth) {
binaryString.insert(contentsOf: "\(internalNumber & 1)", at: binaryString.startIndex)
internalNumber >>= 1
}
return "0b" + binaryString
}
}
Examples:
UInt8(22).binaryDescription // "0b00010110"
Int8(60).binaryDescription // "0b00111100"
Int8(-60).binaryDescription // "0b11000100"
Int16(255).binaryDescription // "0b0000000011111111"
Int16(-255).binaryDescription // "0b1111111100000001"
Went through a lot of answers on this post but I wonder why haven't anyone mentioned the API leadingZeroBitCount on FixedWidthInteger
This returns the number of zeros in specific UInt
eg:
UInt(4).leadingZeroBitCount //61
UInt16(4).leadingZeroBitCount //13
Swift Version
4.1
USAGE
let strFive = String.binaryRepresentation(of: UInt8(5))
print(strFive) // Prints: 00000101
UNDER THE HOOD
extension String {
static func binaryRepresentation<F: FixedWidthInteger>(of val: F) -> String {
let binaryString = String(val, radix: 2)
if val.leadingZeroBitCount > 0 {
return String(repeating: "0", count: val.leadingZeroBitCount) + binaryString
}
return binaryString
}
}
I agree with the others, Although the for-loop seems redundant for repeating a character.
we can simply go with the following String initialiser:
init(count count: Int, repeatedValue c: Character)
usage example:
let string = String(count: 5, repeatedValue: char)
Here is a full example:
let someBits: UInt8 = 0b00001110
let str = String(someBits, radix:2) //binary base
let padd = String(count: (8 - str.characters.count), repeatedValue: Character("0")) //repeat a character
print(padd + str)
If you want binary to have the value of 22, just assign it that: binary = 22 or you could write it as binary = 0b00010110; the two statements are equivalent.
Here's how I would do it:
extension String {
public func pad(with padding: Character, toLength length: Int) -> String {
let paddingWidth = length - self.characters.count
guard 0 < paddingWidth else { return self }
return String(repeating: padding, count: paddingWidth) + self
}
}
String(0b1010, radix: 2).pad(with: "0", toLength: 8) //00001010
So I had this come up recently. The other generic solutions didn't work for me, due to various issues. Anyway, here's my solution (Swift 4):
extension String {
init<B: FixedWidthInteger>(fullBinary value: B) {
self = value.words.reduce(into: "") {
$0.append(contentsOf: repeatElement("0", count: $1.leadingZeroBitCount))
$0.append(String($1, radix: 2))
}
}
}
Tests:
// result: 0000000000000000000000000000000000000000000000000000000000001001
String(fullBinary: 9)
// result: 1111111111111111111111111111111111111111111111111111111100000000
String(fullBinary: -256)
// result: 1111111111111111111111111111111111111111111111111101100011110001
String(fullBinary: -9999)
// result: 0000000000000000000000000000000000000000000000000010011100001111
String(fullBinary: 9999)
// result: 1100011000000000000000000000000000000000000011110110100110110101
String(fullBinary: 14267403619510741429 as UInt)
swift 4.1
extension String {
public func pad(with padding: Character, toLength length: Int) -> String {
let paddingWidth = length - self.count
guard 0 < paddingWidth else { return self }
return String(repeating: padding, count: paddingWidth) + self
}
}
extension UInt8 {
public func toBits() -> String
{
let a = String( self, radix : 2 )
let b = a.pad(with: "0", toLength: 8)
return b
}
}
func showBits( _ list: [UInt8] )
{
for num in list
{
showBits(num)
}
}
func showBits( _ num: UInt8 )
{
//print(num, String( num, radix : 2 ))
print( "\(num) \t" + num.toBits())
}
let initialBits :UInt8 = 0b00001111
let invertedBits = ~initialBits
showBits( [initialBits, invertedBits] )
result
15 00001111
240 11110000
good for you~
There is no difference between binary and decimal numeral systems, when you're working with variables until you want to visualize them or if you want to convert types which can hold different ammount of bits.
In your case is enough to write
var decimal = 22
var binary = UInt8(decimal)
But this will crash (overflow happens) if decimal will hold a value more than 255, because it is maximum value which UInt8 can hold.
Depending on what you want to achieve you can write
var decimal = 261 // 0b100000101
var binary = UInt8(truncatingBitPattern: decimal) // 0b00000101
You'll get 0 as a result, because this initializer will truncate less significant bits.
Second option is
var decimal = 256 // 0b100000000
var binary = UInt8(exactly: decimal) // nil
This initializer returns nil result instead of crashing, if overflow happens.
P.S. If you want to see binary string representation use
String(decimal, radix: 2)
String(binary, radix: 2)
I modified your version to Swift 2.0 count on strings and added a length check:
extension String {
func pad(length: Int) -> String {
let diff = length - self.characters.count
if diff > 0 {
var padded = self
for _ in 0..<diff {
padded = "0" + padded
}
return padded
} else {
return self
}
}
}
Most answers here forget to account for 0, and outputs a representation there is too long.
Based on the answer by #karwag I present:
extension FixedWidthInteger {
var binaryStringRepresentation: String {
words.reduce(into: "") {
$0.append(contentsOf: repeatElement("0", count: $1.leadingZeroBitCount))
if $1 != 0 {
$0.append(String($1, radix: 2))
}
}
}
}
It's a bit overcomplicated, but very fast.
It separates every 4 bits, leaving no white spaces in the string.
extension BinaryInteger {
var binaryDescription: String {
var string = ""
var num = self
let range: UInt64
switch self.bitWidth {
case 8: range = 0x80
case 16: range = 0x8000
case 32: range = 0x80000000
case 64: range = 0x8000000000000000
default: range = 0x0
}
if Self.isSigned {
let mask = Self(range / 2)
let last = num & 1
num >>= 1
for i in 1...self.bitWidth-1 {
string.append("\(num & mask == mask ? 1 : 0)")
num <<= 1
if i % 4 == 0 { string.append(" ") }
}
string.append("\(last)")
} else { // Unsigned
let mask = Self(range)
for i in 1...self.bitWidth {
string.append("\(num & mask == mask ? 1 : 0)")
num <<= 1
if i % 4 == 0 { string.append(" ") }
}
string = String(string.dropLast())
}
return string
}
}
Examples:
UInt8(245).binaryDescription // 1111 0101
Int8(108).binaryDescription // 0110 1100

Precision String Format Specifier In Swift

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!
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
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.
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)
This is a very fast and simple way who doesn't need complex solution.
let duration = String(format: "%.01f", 3.32323242)
// result = 3.3
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)"
}
}
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"
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/
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
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]
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
After iOS 15+ this solution is recommended:
2.31234.formatted(.number.precision(.fractionLength(1)))
Swift 4
let string = String(format: "%.2f", locale: Locale.current, arguments: 15.123)
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
extension Double {
func formatWithDecimalPlaces(decimalPlaces: Int) -> Double {
let formattedString = NSString(format: "%.\(decimalPlaces)f", self) as String
return Double(formattedString)!
}
}
1.3333.formatWithDecimalPlaces(2)
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
//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)
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)")
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
less typing way:
func fprint(format: String, _ args: CVarArgType...) {
print(NSString(format: format, arguments: getVaList(args)))
}
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.
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
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]
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
use below method
let output = String.localizedStringWithFormat(" %.02f %.02f %.02f", r, g, b)
println(output)
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]
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 ""
}
}
#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
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))
}
Swift2 example: Screen width of iOS device formatting the Float removing the decimal
print(NSString(format: "Screen width = %.0f pixels", CGRectGetWidth(self.view.frame)))
#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 …