How to convert a decimal number to binary in Swift? - 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

Related

Middle Character swift

I have an issue I am trying to solve
I am trying to find middle character of the word. If the word's length is odd, return the middle character. If the word's length is even, return the middle 2 characters
func middle(_ str: String) -> String {
let arr = Array(str).map{$0}
print(arr)
// if arr.count
for myInt: String in arr {
if myInt % 2 == 0 {
println("\(myInt) is even number")
} else {
println("\(myInt) is odd number")
}
}
return ""
}
Assuming that your string is the whole word (otherwise you would need to enumerate your string byWords before using this property):
extension StringProtocol {
var middle: SubSequence {
if isEmpty { return "" }
if count == 1 { return self[startIndex...startIndex] }
let middleIndex = index(startIndex, offsetBy: count/2)
let previous = index(before: middleIndex)
return count % 2 == 0 ? self[previous...middleIndex] : self[middleIndex...middleIndex]
}
}
"abc".middle
"abcd".middle
You could use this function:
func middle(_ str: String) -> String {
let count = str.count
if count < 2 {
return str
}
let start = str.index(str.startIndex, offsetBy: (count - 1)/2)
let end = str.index(str.startIndex, offsetBy: (count + 2)/2)
return String(str[start..<end])
}
Here are some use cases:
middle("") //""
middle("1") //"1"
middle("12") //"12"
middle("123") //"2"
middle("1234") //"23"
middle("12345") //"3"
Let's try to approach this systematically. The first task would be to determine the offsets of the first and last character of the “middle part”. If we make a table with some representative cases
string result length first last
------------------------------------
a a 1 0 0
ab ab 2 0 1
abc b 3 1 1
abcd bc 4 1 2
abcde c 5 2 2
abcdef cd 6 2 3
then we can derive that
firstIndex = (length - 1) / 2
lastIndex = length / 2
where / is the truncating integer division. An empty string has to be treated separately.
Finally we need to know how to work with indices and offsets in a Swift string, which is explained in A New Model for Collections and Indices.
This leads to the implementation
func middle(_ str: String) -> String {
if str.isEmpty { return "" }
let len = str.count
let fromIdx = str.index(str.startIndex, offsetBy: (len - 1)/2)
let toIdx = str.index(str.startIndex, offsetBy: len/2)
return String(str[fromIdx...toIdx])
}
here is one more example:
add this extension
extension StringProtocol {
subscript(offset: Int) -> Element {
return self[index(startIndex, offsetBy: offset)]
}
subscript(range: CountableClosedRange<Int>) -> SubSequence {
return prefix(range.lowerBound + range.count)
.suffix(range.count)
}
}
use this like
let stringLength: Int = str.count
if stringLength % 2 == 0{
//even
print(str[((stringLength/2) - 1)...(stringLength/2)])
}else{
//odd
print(str[(stringLength/2) - 1])
}

Converting very large decimal numbers to hexadecimal in swift

We can use String Format specifier to convert an integer value or a long value to hexadecimal notation.
Int Example:
print(String(format:"%x", 1111))
//result:457
Long Example:
print(String(format:"%lx", 11111111111111))
//result:a1b01d4b1c7
But, what if we try to convert a very large decimal that is larger than uint64.max? //18446744073709551615
What is the right way to convert in this case?
One possible solution is to use NSDecimalNumber to hold the large value. But it doesn't have any built in way to convert the number into a string other than base 10.
The following is an extension to NSDecimalNumber that will convert the number into any base from 2 to 16. And it also includes a convenience init that takes a string in a given base.
extension NSDecimalNumber {
convenience init(string: String, base: Int) {
guard base >= 2 && base <= 16 else { fatalError("Invalid base") }
let digits = "0123456789ABCDEF"
let baseNum = NSDecimalNumber(value: base)
var res = NSDecimalNumber(value: 0)
for ch in string {
let index = digits.index(of: ch)!
let digit = digits.distance(from: digits.startIndex, to: index)
res = res.multiplying(by: baseNum).adding(NSDecimalNumber(value: digit))
}
self.init(decimal: res.decimalValue)
}
func toBase(_ base: Int) -> String {
guard base >= 2 && base <= 16 else { fatalError("Invalid base") }
// Support higher bases by added more digits
let digits = "0123456789ABCDEF"
let rounding = NSDecimalNumberHandler(roundingMode: .down, scale: 0, raiseOnExactness: false, raiseOnOverflow: false, raiseOnUnderflow: false, raiseOnDivideByZero: false)
let baseNum = NSDecimalNumber(value: base)
var res = ""
var val = self
while val.compare(0) == .orderedDescending {
let next = val.dividing(by: baseNum, withBehavior: rounding)
let round = next.multiplying(by: baseNum)
let diff = val.subtracting(round)
let digit = diff.intValue
let index = digits.index(digits.startIndex, offsetBy: digit)
res.insert(digits[index], at: res.startIndex)
val = next
}
return res
}
}
Test:
let bigNum = NSDecimalNumber(string: "18446744073709551615")
print(bigNum.toBase(16))
print(bigNum.toBase(10)) // or just print(bigNum)
print(NSDecimalNumber(string: "B7", base: 16))
print(NSDecimalNumber(string: NSDecimalNumber(string: "18446744073709551615").toBase(16), base: 16))
Output:
FFFFFFFFFFFFFFFF
18446744073709551615
183
18446744073709551615

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

How do i convert HexString To ByteArray in Swift 3

I'm was trying to convert hexString to Array of Bytes([UInt8]) I searched everywhere but couldn't find a solution. Below is my swift 2 code
func stringToBytes(_ string: String) -> [UInt8]? {
let chars = Array(string)
let length = chars.count
if length & 1 != 0 {
return nil
}
var bytes = [UInt8]()
bytes.reserveCapacity(length/2)
for var i = 0; i < length; i += 2 {
if let a = find(hexChars, chars[i]),
let b = find(hexChars, chars[i+1]) {
bytes.append(UInt8(a << 4) + UInt8(b))
} else {
return nil
}
}
return bytes
}
Example Hex
Hex : "7661706f72"
expectedOutput : "vapor"
This code can generate the same output as your swift 2 code.
func stringToBytes(_ string: String) -> [UInt8]? {
let length = string.characters.count
if length & 1 != 0 {
return nil
}
var bytes = [UInt8]()
bytes.reserveCapacity(length/2)
var index = string.startIndex
for _ in 0..<length/2 {
let nextIndex = string.index(index, offsetBy: 2)
if let b = UInt8(string[index..<nextIndex], radix: 16) {
bytes.append(b)
} else {
return nil
}
index = nextIndex
}
return bytes
}
let bytes = stringToBytes("7661706f72")
print(String(bytes: bytes!, encoding: .utf8)) //->Optional("vapor")
Here is a sketch of how I'd do it in a more idiomatic Swift style (this might be Swift 4 only):
func toPairsOfChars(pairs: [String], string: String) -> [String] {
if string.count == 0 {
return pairs
}
var pairsMod = pairs
pairsMod.append(String(string.prefix(2)))
return toPairsOfChars(pairs: pairsMod, string: String(string.dropFirst(2)))
}
func stringToBytes(_ string: String) -> [UInt8]? {
// omit error checking: remove '0x', make sure even, valid chars
let pairs = toPairsOfChars(pairs: [], string: string)
return pairs.map { UInt8($0, radix: 16)! }
}
Following code may be help for you
extension String {
/// Create `Data` from hexadecimal string representation
///
/// This takes a hexadecimal representation and creates a `Data` object. Note, if the string has any spaces or non-hex characters (e.g. starts with '<' and with a '>'), those are ignored and only hex characters are processed.
///
/// - returns: Data represented by this hexadecimal string.
func hexadecimal() -> Data? {
var data = Data(capacity: characters.count / 2)
let regex = try! NSRegularExpression(pattern: "[0-9a-f]{1,2}", options: .caseInsensitive)
regex.enumerateMatches(in: self, options: [], range: NSMakeRange(0, characters.count)) { match, flags, stop in
let byteString = (self as NSString).substring(with: match!.range)
var num = UInt8(byteString, radix: 16)!
data.append(&num, count: 1)
}
guard data.count > 0 else {
return nil
}
return data
}
}
extension String {
/// Create `String` representation of `Data` created from hexadecimal string representation
///
/// This takes a hexadecimal representation and creates a String object from that. Note, if the string has any spaces, those are removed. Also if the string started with a `<` or ended with a `>`, those are removed, too.
init?(hexadecimal string: String) {
guard let data = string.hexadecimal() else {
return nil
}
self.init(data: data, encoding: .utf8)
}
/// - parameter encoding: The `NSStringCoding` that indicates how the string should be converted to `NSData` before performing the hexadecimal conversion.
/// - returns: `String` representation of this String object.
func hexadecimalString() -> String? {
return data(using: .utf8)?
.hexadecimal()
}
}
extension Data {
/// Create hexadecimal string representation of `Data` object.
/// - returns: `String` representation of this `Data` object.
func hexadecimal() -> String {
return map { String(format: "%02x", $0) }
.joined(separator: "")
}
}
Use like this :
let hexString = "68656c6c 6f2c2077 6f726c64"
print(String(hexadecimalString: hexString))
Or
let originalString = "hello, world"
print(originalString.hexadecimalString())
After lot searching and thinking here is how you do it
func toByteArray( _ hex:String ) -> [UInt8] {
// remove "-" from Hexadecimal
var hexString = hex.removeWord( "-" )
let size = hexString.characters.count / 2
var result:[UInt8] = [UInt8]( repeating: 0, count: size ) // array with length = size
// for ( int i = 0; i < hexString.length; i += 2 )
for i in stride( from: 0, to: hexString.characters.count, by: 2 ) {
let subHexStr = hexString.subString( i, length: 2 )
result[ i / 2 ] = UInt8( subHexStr, radix: 16 )! // ! - because could be null
}
return result
}
extension String {
func subString( _ from: Int, length: Int ) -> String {
let size = self.characters.count
let to = length + from
if from < 0 || to > size {
return ""
}
var result = ""
for ( idx, char ) in self.characters.enumerated() {
if idx >= from && idx < to {
result.append( char )
}
}
return result
}
func removeWord( _ word:String ) -> String {
var result = ""
let textCharArr = Array( self.characters )
let wordCharArr = Array( word.characters )
var possibleMatch = ""
var i = 0, j = 0
while i < textCharArr.count {
if textCharArr[ i ] == wordCharArr[ j ] {
if j == wordCharArr.count - 1 {
possibleMatch = ""
j = 0
}
else {
possibleMatch.append( textCharArr[ i ] )
j += 1
}
}
else {
result.append( possibleMatch )
possibleMatch = ""
if j == 0 {
result.append( textCharArr[ i ] )
}
else {
j = 0
i -= 1
}
}
i += 1
}
return result
}
}
Refer this video to know how I did it.
Credit : AllTech
Conversion of String to Data with nicer syntax.
static func hexStringToData(string: String) -> Data {
let stringArray = Array(string)
var data: Data = Data()
for i in stride(from: 0, to: string.count, by: 2) {
let pair: String = String(stringArray[i]) + String(stringArray[i+1])
if let byteNum = UInt8(pair, radix: 16) {
let byte = Data([byteNum])
data.append(byte)
}
else{
fatalError()
}
}
return data
}

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 …