32

What I want to know is the most code efficient way to convert (in swift 2):

  • Decimal to Binary
  • Binary to Decimal
  • Decimal to Hexadecimal
  • Hexadecimal to Decimal
  • Binary to Hexadecimal
  • Hexadecimal to Binary

I already have a rudimentary and long-winded way of achieving this, but I would like to find a more efficient way.

Cobie Fisher
  • 713
  • 2
  • 8
  • 18

3 Answers3

81

Both String and Int have initializers which take a radix (base). Combining those, you can achieve all of the conversions:

// Decimal to binary
let d1 = 21
let b1 = String(d1, radix: 2)
print(b1) // "10101"

// Binary to decimal
let b2 = "10110"
let d2 = Int(b2, radix: 2)!
print(d2) // 22

// Decimal to hexadecimal
let d3 = 61
let h1 = String(d3, radix: 16)
print(h1) // "3d"

// Hexadecimal to decimal
let h2 = "a3"
let d4 = Int(h2, radix: 16)!
print(d4) // 163

// Binary to hexadecimal
let b3 = "10101011"
let h3 = String(Int(b3, radix: 2)!, radix: 16)
print(h3) // "ab"

// Hexadecimal to binary
let h4 = "face"
let b4 = String(Int(h4, radix: 16)!, radix: 2)
print(b4) // "1111101011001110"
vacawama
  • 150,663
  • 30
  • 266
  • 294
  • @vacawama, what happens if the Hex value is 32 chars? I am trying to convert a 32 char -database generated GUID - to an int.. – rustyMagnet Oct 23 '16 at 13:52
  • @rustyMagnet, a 32 character hex value would represent a 128-bit integer. What would you do with that? – vacawama Oct 23 '16 at 15:15
  • 2
    @rustyMagnet: You probably want to convert that into a UUID, which is the Swift (and Java) equivalent of a GUID. – RenniePet Feb 06 '17 at 23:59
  • Could you please provide an example to convert a signed Int (eg: -52) to binary then hexadecimal please @vacawama – H4Hugo Oct 03 '18 at 12:17
  • 1
    @H4Hugo, `String(UInt64(bitPattern: -52), radix: 2)`, `String(UInt64(bitPattern: -52), radix: 16)` – vacawama Oct 03 '18 at 12:33
  • @AnonProgrammer, what would I do about what? Bit manipulation isn't a question. – vacawama Jul 29 '19 at 23:40
  • @vacawama I should have clarified. This is in reference to your comment where you asked "what would you do with that". I have 32 char hex value and can't seem to convert to UUID. any way I try I get this error `Integer literal '87467891491305692429810459546405' overflows when stored into 'Int'` Actual hex is `0x00000450000010000000009132591325` – AnonProgrammer Jul 29 '19 at 23:45
  • @vacawama I want to convert this string '3c1878900216d211aa9e0924' to binary but getting nil { Int(h4, radix: 16 ) } (maybe because of characters are out of bounds), so could you know any way how can i convert it to binary. – VSP Nov 27 '19 at 00:49
  • @VSP, when you say binary, do you mean a String containing “0” and “1”, or do you want an array of bytes like `[UInt8]`? – vacawama Nov 27 '19 at 01:54
  • @Ribena, negative numbers are usually represented in complement form. You'll want to do something like: `String(UInt64(bitPattern: -52), radix: 16)` – vacawama Dec 14 '20 at 23:52
  • The title says "Convert Hexa to **Decimal** in Swift" How is Int(h2, radix: 16)! considered a Decimal ? – iOS Blacksmith Sep 06 '22 at 07:54
3

Swift Converter 2, 8, 10, 16

A bunch of Int and String is used to convert different systems.

Int is used for working with decimal
String is used for other types

It is safe to convert a string representation of system to decimal and decimal to string representation

String -> Int -> String

There are samples of

binary(2) - 0b
octal(8) - 0o
decimal(10)
hexadecimal(16) - 0x
extension Int {
    
    //From Decimal
    //10 -> 2
    func decToBinString() -> String {
        let result = createString(radix: 2)
        return result
    }
    
    //10 -> 8
    func decToOctString() -> String {
//        let result = decToOctStringFormat()
        let result = createString(radix: 8)
        
        return result
    }
    
    //10 -> 16
    func decToHexString() -> String {
//        let result = decToHexStringFormat()
        let result = createString(radix: 16)
        return result
    }
    
    //10 -> 8
    func decToOctStringFormat(minLength: Int = 0) -> String {

        return createString(minLength: minLength, system: "O")
    }

    //10 -> 16
    func decToHexStringFormat(minLength: Int = 0) -> String {

        return createString(minLength: minLength, system: "X")
    }
    
    fileprivate  func createString(radix: Int) -> String {
        return String(self, radix: radix, uppercase: true)
    }
    
    fileprivate func createString(minLength: Int = 0, system: String) -> String {
        //0 - fill empty space by 0
        //minLength - min count of chars
        //system - system number
        return String(format:"%0\(minLength)\(system)", self)
    }
}
extension String {
    
    //To Decimal
    //2 -> 10
    func binToDec() -> Int {
        return createInt(radix: 2)
    }
    
    //8 -> 10
    func octToDec() -> Int {
        return createInt(radix: 8)
    }
    
    //16 -> 10
    func hexToDec() -> Int {
        return createInt(radix: 16)
    }
    
    //Others
    //2 -> 8
    func binToOct() -> String {
        return self.binToDec().decToOctString()
    }
    
    //2 -> 16
    func binToHex() -> String {
        return self.binToDec().decToHexString()
    }
    
    //8 -> 16
    func octToHex() -> String {
        return self.octToDec().decToHexString()
    }
    
    //16 -> 8
    func hexToOct() -> String {
        return self.hexToDec().decToOctString()
    }
    
    //16 -> 2
    func hexToBin() -> String {
        return self.hexToDec().decToBinString()
    }
    
    //8 -> 2
    func octToBin() -> String {
        return self.octToDec().decToBinString()
    }

    //Additional
    //16 -> 2
    func hexToBinStringFormat(minLength: Int = 0) -> String {
        
        return hexToBin().pad(minLength: minLength)
    }
    
    fileprivate func pad(minLength: Int) -> String {
        let padCount = minLength - self.count
        
        guard padCount > 0 else {
            return self
        }

        return String(repeating: "0", count: padCount) + self
    } 

    fileprivate func createInt(radix: Int) -> Int {
        return Int(self, radix: radix)!
    }
    
}

Tests:

func testConverter() {
    let decInt = 13511
    let binStr = "11010011000111"
    let octStr = "32307"
    let hexStr = "34C7"
    
    //From Decimal
    //10 -> 2
    XCTAssertEqual(binStr, decInt.decToBinString())
    //10 -> 8
    XCTAssertEqual(octStr, decInt.decToOctString())
    //10 -> 16
    XCTAssertEqual(hexStr, decInt.decToHexString())
    
    //To Decimal
    //2 -> 10
    XCTAssertEqual(decInt, binStr.binToDec())
    //8 -> 10
    XCTAssertEqual(decInt, octStr.octToDec())
    //16 -> 10
    XCTAssertEqual(decInt, hexStr.hexToDec())
    
    //Others
    //2 -> 8
    XCTAssertEqual(octStr, binStr.binToOct())
    //2 -> 16
    XCTAssertEqual(hexStr, binStr.binToHex())
    //8 -> 16
    XCTAssertEqual(hexStr, octStr.octToHex())
    //16 -> 8
    XCTAssertEqual(octStr, hexStr.hexToOct())
    //16 -> 2
    XCTAssertEqual(binStr, hexStr.hexToBin())
    //8 -> 2
    XCTAssertEqual(binStr, octStr.octToBin())

    //String format feature
    //10 -> 8
    XCTAssertEqual("017", (15).decToOctStringFormat(minLength: 3))
    //10 -> 16
    XCTAssertEqual("00F", (15).decToHexStringFormat(minLength: 3))
    //16 -> 2
    XCTAssertEqual("0011010011000111", hexStr.hexToBinStringFormat(minLength: 16))
    
}
yoAlex5
  • 29,217
  • 8
  • 193
  • 205
0

from decimal to binary

extension Int {
    //10 -> "2"
    func decToBinString() -> String {
        return String(self, radix: 2, uppercase: true)
    }
}

extension String {
    //"2" -> 10
    func binToDec() -> Int {
        return Int(self, radix: 2)!
    }
}
Bassant Ashraf
  • 1,531
  • 2
  • 16
  • 23
  • That forced unwrap on the String extension is dangerous, as it can crash the app, better have the method return an optional, this way its callers know at compile time that it can fail, instead of getting a crash at runtime. – Cristik Jul 03 '21 at 05:04