如何在swift中从用户那里获取二进制字符串输入

时间:2018-04-24 06:42:53

标签: ios swift

我想从二进制文件中获取用户的输入,我想要的是: 10101 11110

然后我需要对此执行按位OR。我知道如何获取输入以及如何执行按位OR,只是我想知道如何转换因为我当前使用的是没有给出正确的结果。我尝试的内容如下:

let aBits: Int16 = Int16(a)! //a is String "10101"
let bBits: Int16 = Int16(b)! //b is String "11110"
let combinedbits = aBits | bBits

编辑:我不需要使用基数进行十进制到二进制转换,因为我的字符串已经只有0和1 字符串最多可包含500个字符,如: 10011011111010110111001011001001101110111110110001001111001111101111010110110111 00111001100011111010 这超出了Int限制,如何在Swift中处理它?<​​/ p>

Edit2:根据vacawama的回答,下面的代码效果很好:

let maxAB = max(a.count, b.count)
let paddedA = String(repeating: "0", count: maxAB - a.count) + a
let paddedB = String(repeating: "0", count: maxAB - b.count) + b

let Str = String(zip(paddedA, paddedB).map({ $0 == ("0", "0") ? "0" : "1" }))

我可以拥有最多500个字符串的数组,每个字符串最多可以包含500个字符。然后我必须得到所有可能的对并执行按位OR并计算1的最大数量。是否有任何想法使上述解决方案更有效?谢谢

4 个答案:

答案 0 :(得分:3)

由于你需要任意长的二进制数,所以用字符串做所有事情。

此函数首先将两个输入填充到相同的长度,然后使用zip将数字与map配对,以计算每对字符的OR。生成的字符数组将转换回String String()

func binaryOR(_ a: String, _ b: String) -> String {
    let maxAB = max(a.count, b.count)
    let paddedA = String(repeating: "0", count: maxAB - a.count) + a
    let paddedB = String(repeating: "0", count: maxAB - b.count) + b

    return String(zip(paddedA, paddedB).map({ $0 == ("0", "0") ? "0" : "1" }))
}

print(binaryOR("11", "1100"))    // "1111"
print(binaryOR("1000", "0001"))  // "1001"
  

我可以拥有最多500个字符串的数组,每个字符串最多可以有500个字符串   字符。然后我必须得到所有可能的对并按位执行   或者计算1的最大数量。任何想法做出上述解决方案   效率更高?

您必须执行500 * 499 / 2124,750比较)。重要的是避免不必要的和/或重复的工作。

我建议:

  1. 执行初始传递以循环查找字符串以查找最大字符串的长度。然后将所有字符串填充到此长度。我会跟踪每个字符串的原始长度:

    struct BinaryNumber {
        var string: String  // padded string
        var length: Int     // original length before padding
    }
    
  2. 修改binaryOR函数以取BinaryNumbers并返回Int,即&#34; 1&#34; s中的数量。

    func binaryORcountOnes(_ a: BinaryNumber, _ b: BinaryNumber) -> Int { 
        let maxAB = max(a.length, b.length)           
        return zip(a.string.suffix(maxAB), b.string.suffix(maxAB)).reduce(0) { total, pair in return total + (pair == ("0", "0") ? 0 : 1) }
    }
    

    注意:suffix的使用仅通过检查重要的数字来提高效率。如果原始字符串的长度为23,则只有最后3个数字才会被删除,即使它们被填充到500长度。< / p>

  3. 循环并比较所有BinaryNumber对以查找最大的一对:

    var numbers: [BinaryNumber]  // This array was created in step 1
    
    maxOnes = 0
    for i in 0 ..< (numbers.count - 1) {
        for j in (i + 1) ..< numbers.count {
            let ones = binaryORcountOnes(numbers[i], numbers[j])
            if ones > maxOnes {
                maxOnes = ones
            }
        }
    }
    
    print("maxOnes = \(maxOnes)")
    
  4. 加速的其他想法

    或者不能创建比原始两个数字更多的那些,并且1的数量不能超过原始两个数字中任何一个的最大长度。因此,如果您在填充每个数字时计算每个数字并将其存储在struct var ones: Int属性中的binaryORcountOnes中,则可以使用它来查看是否应该打扰{{1} }:

    maxOnes = 0
    for i in 0 ..< (numbers.count - 1) {
        for j in (i + 1) ..< numbers.count {
            if maxOnes < min(numbers[i].ones + numbers[j].ones, numbers[i].length, numbers[j].length) {
                let ones = binaryORcountOnes(numbers[i], numbers[j])
                if ones > maxOnes {
                    maxOnes = ones
                }
            }
        }
    }
    

    顺便说一下,原始字符串的length实际上应该是包含最高阶1的最小长度。因此,如果原始字符串为"00101",则length应为3,因为这就是您存储"101"所需的全部内容。

答案 1 :(得分:0)

let number = Int(a, radix: 2)

Radix帮助使用二进制而不是分数值

答案 2 :(得分:0)

您可以使用radix转换字符串。转换后,您可以执行按位OR,然后检查nonzeroBitCount以计算1的数量

let a = Int("10101", radix: 2)!
let b = Int("11110", radix: 2)!

let bitwiseOR = a | b
let nonZero = bitwiseOR.nonzeroBitCount

答案 3 :(得分:0)

正如我上面已经评论的那样,“10101”实际上是String而不是Binary,因此"10101" | "11110"无法计算您实际需要的内容。

所以您需要做的是转换decimal中的两个值,然后使用bitwiseOR并将结果转换回Binary String (in which format you have the data "11111" not 11111)

let a1 = Int("10101", radix: 2)!
let b1 = Int("11110", radix: 2)!
var result = 21 | 30
print(result)
  

输出 31

现在将其转换回binary string

let binaryString = String(result, radix: 2)
print(binaryString)
  

输出 11111

- :编辑: -

我将回答一个如何计算bitwiseOR的基本示例,因为该问题特定于不使用内置函数,因为字符串非常大,无法转换为Int

  

算法: 1 | 0 = 1,1 | 1 = 1,0 | 0 = 0,0 | 1 = 1

因此,我们所做的是逐个从String获取所有字符,执行|操作并将其附加到另一个String

var str1 = "100101" // 37
var str2 = "10111" // 23
/// Result should be "110111" -> "55"

// #1. Make both string equal
let length1 = str1.characters.count
let length2 = str2.characters.count
if length1 != length2 {
    let maxLength = max(length1, length2)
    for index in 0..<maxLength {
        if str1.characters.count < maxLength {
            str1 = "0" + str1
        }
        if str2.characters.count < maxLength {
            str2 = "0" + str2
        }
    }
}

// #2. Get the index and compare one by one in bitwise OR
// a) 1 - 0 = 1,
// b) 0 - 1 = 1,
// c) 1 - 1 = 1,
// d) 0 - 0 = 0
let length = max(str1.characters.count, str2.characters.count)
var newStr = ""
for index in 0..<length {
    let charOf1 = Int(String(str1[str1.index(str1.startIndex, offsetBy: index)]))!
    let charOf2 = Int(String(str2[str2.index(str2.startIndex, offsetBy: index)]))!
    let orResult = charOf1 | charOf2
    newStr.append("\(orResult)")
}

print(newStr)
  

输出:110111 // 55

我想提及Understanding Bitwise Operators了解更多细节。