【问题标题】:How to convert a decimal number to binary in Swift?如何在 Swift 中将十进制数转换为二进制数?
【发布时间】:2014-11-28 15:30:35
【问题描述】:

如何在 Swift 中将 Int 转换为 UInt8? 例子。我想将数字 22 转换为 0b00010110

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

【问题讨论】:

  • 数字没有基数,除非你想显示它们。
  • var decimal = 22; 那就是二进制数1*(2^4) + 1*(2^2) + 1*2;
  • 您的问题(基于 cmets)实际上是:“我如何快速异或字节?”
  • @Kevin,这是什么意思?
  • @ScottyBlades 数字是一个抽象概念,数字只是我们交流它们的方式。如果我有 22 个苹果,我说我有 22、0b10110、026、0x16 或 10(以 22 为基数)并不重要,我有完全相同数量的苹果。类似地,如果一个变量的值为 22,那么无论您将其写入哪个基数,该值仍然是 22。

标签: swift


【解决方案1】:

您可以使用带有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

【讨论】:

  • 我需要一个 UInt8 中的数字。我想使用字节。异或的例子:
  • 如果您想将现有的Int 转换为UInt8 类型,您可以简单地使用UInt8() 初始化器,并传入Int 类型。或者如果你想直接分配一个UInt8 变量,提前知道值,使用let myBits = 0b00010110
  • 谢谢!它帮助了我。我怎样才能打印ln(UInt8)?我想查看字节而不是十进制值。
  • 我的回答应该对你有所帮助。
  • 你是对的,我一定是写错了。我复制并粘贴了,现在可以使用了。
【解决方案2】:

Swift 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"

【讨论】:

    【解决方案3】:

    这里的大多数答案都忘记了 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】:

      在这篇文章中查看了很多答案,但我想知道为什么没有人在 FixedWidthInteger 上提到 API leadingZeroBitCount

      这将返回特定 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
          }
      }
      

      【讨论】:

        【解决方案5】:

        由于没有一个解决方案考虑负数,我想出了一个简单的解决方案,它基本上读取数字的内部表示并将其自动填充到其类型的宽度。这应该适用于所有 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"
        

        【讨论】:

          【解决方案6】:

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

          对你有好处~

          【讨论】:

            【解决方案7】:

            所以我最近提出了这个问题。由于各种问题,其他通用解决方案对我不起作用。无论如何,这是我的解决方案(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)
            

            【讨论】:

            • 刚刚看到这个。我发布了类似的方法。这看起来既聪明又干净
            【解决方案8】:

            我会这样做:

            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
            

            【讨论】:

            • 什么不可用?
            【解决方案9】:

            二进制和十进制数字系统之间没有区别,当您使用变量直到您想要可视化它们或者如果您想要转换可以容纳不同位数的类型时。

            在你的情况下就足够了

            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 结果而不是崩溃。

            附:如果您想查看二进制字符串表示,请使用

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

            【讨论】:

            • UInt8(decimal) 和 UInt8(exactly: 不产生二进制表示。TruncatingBitPattern 不可用。
            【解决方案10】:

            我将某人的版本修改为 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"
            

            【讨论】:

              【解决方案11】:

              我同意其他人的观点,尽管 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)
              

              【讨论】:

                【解决方案12】:

                我将您的版本修改为 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
                    }
                 }
                }
                

                【讨论】:

                  【解决方案13】:

                  如果您希望binary 具有22 的值,只需将其指定为:binary = 22 或者您可以将其写为binary = 0b00010110;这两个语句是等价的。

                  【讨论】:

                    猜你喜欢
                    • 2015-01-03
                    • 2011-01-08
                    • 2010-12-08
                    • 1970-01-01
                    • 2017-02-18
                    • 2016-09-03
                    • 2020-10-27
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多