簡體   English   中英

如何將Swift中的十進制數轉換為二進制數?

[英]How to convert a decimal number to binary in Swift?

如何在 Swift 中將 Int 轉換為 UInt8? 例子。 我想將數字 22 轉換為 0b00010110

var decimal = 22
var binary:UInt8 = ??? //What should I write here?

您可以使用帶radix參數的String初始值設定項將十進制值轉換為人類可讀的二進制表示

let num = 22
let str = String(num, radix: 2)
print(str) // prints "10110"

如果你願意,你也可以很容易地用任意數量的零填充它:

斯威夫特 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

斯威夫特 5.1 / Xcode 11

謝古斯塔沃·塞德勒 我對他的解決方案的版本補充可讀性的空格

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
    }
}

例子:

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"

我將某人的版本修改為 swift 3.0 使用正確的初始值設定項來創建具有重復值的字符串

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"

由於沒有一個解決方案考慮負數,我想出了一個簡單的解決方案,它基本上讀取數字的內部表示並將其自動填充到其類型的寬度。 這應該適用於所有BinaryInteger類型。

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
    }
}

例子:

UInt8(22).binaryDescription     // "0b00010110"
Int8(60).binaryDescription      // "0b00111100"
Int8(-60).binaryDescription     // "0b11000100"
Int16(255).binaryDescription    // "0b0000000011111111"
Int16(-255).binaryDescription   // "0b1111111100000001"

在這篇文章中經歷了很多答案,但我想知道為什么沒有人提到leadingZeroBitCount上的 APIleadingZeroBitCount

這將返回特定 UInt 中的零數,例如:

UInt(4).leadingZeroBitCount //61

UInt16(4).leadingZeroBitCount //13

迅捷版

4.1

用法

let strFive = String.binaryRepresentation(of: UInt8(5))
print(strFive) // Prints: 00000101 

在引擎蓋下

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
    }
}

我同意其他人的看法,盡管 for 循環對於重復字符似乎是多余的。
我們可以簡單地使用以下字符串初始化程序:

init(count count: Int, repeatedValue c: Character)

用法示例:

let string = String(count: 5, repeatedValue: char)

這是一個完整的例子:

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)

如果您希望binary的值為22 ,只需將其分配為: binary = 22或者您可以將其寫為binary = 0b00010110 ; 這兩個語句是等價的。

這是我將如何做到的:

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

快速 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] )

結果

15 00001111

240 11110000

對你有好處~

二進制和十進制數字系統之間沒有區別,當您使用變量直到您想要將它們可視化或者您想要轉換可以容納不同位數的類型時。

在你的情況下就足以寫

var decimal = 22
var binary = UInt8(decimal)

但是如果decimal將保存超過 255 的值,這將崩潰(發生溢出),因為它是UInt8可以保存的最大值。

根據您想要實現的目標,您可以編寫

var decimal = 261 // 0b100000101
var binary = UInt8(truncatingBitPattern: decimal) // 0b00000101

結果你會得到0 ,因為這個初始值設定項會截斷不太重要的位。

第二個選擇是

var decimal = 256  // 0b100000000
var binary = UInt8(exactly: decimal) // nil

如果發生溢出,此初始化程序將返回nil結果而不是崩潰。

PS如果你想看到二進制字符串表示使用

String(decimal, radix: 2)
String(binary, radix: 2)

所以我最近出現了這個。 由於各種問題,其他通用解決方案對我不起作用。 無論如何,這是我的解決方案(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))
    }
  }
}

測試:

// 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 2.0 count on strings 並添加了長度檢查:

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
    }
 }
}

這里的大多數答案都忘記考慮 0,並輸出一個太長的表示。

根據@karwag 的回答,我提出:

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))
            }
        }
    }
}

這有點過於復雜,但非常快。 它每 4 位分隔一次,字符串中不留空格。

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
    }   
}

例子:

UInt8(245).binaryDescription  // 1111 0101
Int8(108).binaryDescription   // 0110 1100

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM