为什么我不能在Swift中使用位操作得到负数?

时间:2016-07-12 16:41:39

标签: swift bit-manipulation

这是一个LeetCode问题。我在该问题的不同版本中写了4个答案。当我尝试使用"位操作"时,我收到了错误。由于LeetCode中没有人可以回答我的问题,而且我无法找到任何有关此问题的Swift文档。我以为我会试着在这里问。

问题是在给定数组中获得多数元素(> n / 2)。以下代码适用于其他语言,如 Java ,因此我认为它可能是Swift中的一般问题

func majorityElement(nums: [Int]) -> Int {
    var bit = Array(count: 32, repeatedValue: 0)
    for num in nums {
        for i in 0..<32 {
            if (num>>(31-i) & 1) == 1 {
                bit[i] += 1
            }
        }
    }
    var ret = 0
    for i in 0..<32 {
        bit[i] = bit[i]>nums.count/2 ? 1 : 0
        ret += bit[i] * (1<<(31-i))
    }
    return ret
}

当输入为 [ - 2147483648] 时,输出为2147483648.但在Java中,它可以成功输出正负数。

Swift doc说:

  

即使在32位平台上,Int也可以存储-2,147,483,648和2,147,483,647之间的任何值,并且对于许多整数范围来说足够大。

嗯, 2,147,483,647 ,输入比该数字大1。当我在游乐场中运行pow(2.0, 31.0)时,会显示 2147483648 。我很困惑。我的代码有什么问题,或者我错过了什么 Swift Int

1 个答案:

答案 0 :(得分:2)

Java int是32位整数。 Swift Int是32位或64位 取决于平台。特别是,它在所有OS X上都是64位 可以使用Swift的平台。

您的代码只处理给定整数的低32位,因此

-2147483648 = 0xffffffff80000000

变为

2147483648 = 0x0000000080000000

因此解决问题,您可以更改函数以将32位整数作为参数:

func majorityElement(nums: [Int32]) -> Int32 { ... }

或通过计算使其适用于任意大小的整数 实际大小和使用而不是常量32

func majorityElement(nums: [Int]) -> Int {
    let numBits = sizeof(Int) * 8
    var bit = Array(count: numBits, repeatedValue: 0)
    for num in nums {
        for i in 0..<numBits {
            if (num>>(numBits-1-i) & 1) == 1 {
                bit[i] += 1
            }
        }
    }
    var ret = 0
    for i in 0..<numBits {
        bit[i] = bit[i]>nums.count/2 ? 1 : 0
        ret += bit[i] * (1<<(numBits-1-i))
    }
    return ret
}

更灵活的方式是使用map()reduce()

func majorityElement(nums: [Int]) -> Int {
    let numBits = sizeof(Int) * 8
    let bitCounts = (0 ..< numBits).map { i in
        nums.reduce(0) { $0 + ($1 >> i) & 1 }
    }
    let major = (0 ..< numBits).reduce(0) {
        $0 | (bitCounts[$1] > nums.count/2 ? 1 << $1 : 0)
    }
    return major
}