How to convert a decimal number to binary in Swift?
Asked Answered
P

14

92

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?
Pinnatiped answered 3/10, 2014 at 14:47 Comment(5)
Numbers have no base until you want to display them.Crenelate
var decimal = 22; that is it that is a binary number 1*(2^4) + 1*(2^2) + 1*2;Bundy
your question (based on comments) is actually: "how do I XOR bytes in swift?"Bundy
@Kevin, what does that mean?Cima
@Cima numbers are an abstract idea, numerals are simply our way of communicating them. If I have 22 apples, it doesn't matter if I say I have 22, 0b10110, 026, 0x16, or 10(base 22), I have exactly the same number of apples. Similarly, if a variable has the value 22, it doesn't matter what base you write that in, the value is still 22.Crenelate
N
219

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
Nostology answered 3/10, 2014 at 14:52 Comment(8)
I need a number in UInt8. I want to work with bytes. Example to make XOR:Pinnatiped
You can simply use the UInt8() initializer, and pass in an Int type, if you want to convert an existing Int to a UInt8 type. Or if you want to assign a UInt8 variable directly, knowing the value ahead of time, using let myBits = 0b00010110.Nostology
Thanks! It helped me. How can I println(UInt8)? I want to see bytes instead of decimal value.Pinnatiped
My answer should help you with that.Nostology
radix is no longer availableCima
@Cima Are you sure? It looks like it's still in the docs: developer.apple.com/documentation/swift/string/2885001-initNostology
You're right, I must have written it wrong. I copied and pasted, now its working.Cima
repeatElement ("0", count : 8 - str.count ) + str )Carboniferous
H
26

Swift 5 / Xcode 14

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"
Herbherbaceous answered 12/5, 2019 at 13:31 Comment(0)
H
10

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
    }
}
Honk answered 2/12, 2018 at 19:9 Comment(0)
I
8

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"
Itself answered 30/9, 2016 at 12:41 Comment(0)
M
8

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"
Monroe answered 16/8, 2018 at 18:7 Comment(0)
T
7

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)
Tiber answered 8/3, 2016 at 9:40 Comment(0)
V
3

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.

Victoriavictorian answered 3/10, 2014 at 14:51 Comment(0)
H
3

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
Haileyhailfellowwellmet answered 5/8, 2016 at 12:48 Comment(1)
What's unavailable?Haileyhailfellowwellmet
I
3

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)
Ixtle answered 18/12, 2017 at 18:37 Comment(1)
just saw this. I posted a similar approach. this looks clever and cleanerHonk
T
3

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~

Teshatesla answered 24/7, 2018 at 5:17 Comment(0)
A
2

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)
Arawakan answered 25/10, 2016 at 10:8 Comment(1)
UInt8(decimal), and UInt8(exactly: do not produce binary representations. TruncatingBitPattern isn't available.Cima
F
0

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
    }
 }
}
Fellatio answered 30/9, 2015 at 14:55 Comment(0)
H
0

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))
            }
        }
    }
}
Hairball answered 2/7, 2019 at 16:43 Comment(0)
C
0

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
Calie answered 13/1, 2023 at 16:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.