【问题标题】:How to calculate checksum in swift?如何快速计算校验和?
【发布时间】:2018-10-31 06:25:40
【问题描述】:

我想计算校验和。我对 crc 的预期答案是 0xE1 但是当我运行这段代码时,它返回 0。我没有得到任何解决方案来做到这一点。请帮我解决这个问题。 下面是我尝试过的代码。

我的视图控制器:

    class ViewController: UIViewController {
    var checkSum:UInt8 = 0
    override func viewDidLoad() {
            super.viewDidLoad()
    let bytes = [0x01,0x0B,0x00,0x0B,0x03,0x07,0x12,0x0E,0x0C,0x10,0x09,0x12,0x0C,0x19,0x09,0xFF,0x14]
        for item in bytes {
            print(calculateCheckSum(crc: checkSum, byteValue: UInt8(item)))
        }
    }

func calculateCheckSum(crc:UInt8, byteValue: UInt8) -> UInt8 {

        let generator = 0x1D

        checkSum = crc ^ byteValue

        for _ in 1...8 {
            if (crc & 0x80 != 0) {
                checkSum = (crc << 1) ^ UInt8(Int8(generator))
            }
            else {
                checkSum <<= UInt8(1)
            }
        }
        return crc
    }
}

【问题讨论】:

  • 如果crc &amp; 0x80 != 0,您的 for 循环只会运行 8 次相同的事情。 crc 没有改变,self.crc 只是被分配了 8 次相同的值。不要将self.crc 与参数名称混淆。尝试重命名其中一个并检查您的代码,看看您是否编写了您想要的内容。
  • @Dhasal 不要在calculateCheckSum 中使用变量checkSum 根本

标签: ios swift checksum


【解决方案1】:

重写以避免错误地使用全局checkSum 变量。

func calculateCheckSum(crc:UInt8, byteValue: UInt8) -> UInt8 {
    let generator: UInt8 = 0x1D

    // a new variable has to be declared inside this function
    var newCrc = crc ^ byteValue

    for _ in 1...8 {
        if newCrc & 0x80 != 0 {
            newCrc = (newCrc << 1) ^ generator
        }
        else {
            newCrc <<= 1
        }
    }
    return newCrc
}

另外,您似乎没有正确使用该方法的结果:

var checkSum: UInt8 = 0
let bytes = [...]
for item in bytes {
   checkSum = calculateCheckSum(crc: checkSum, byteValue: UInt8(item))
}

print(checkSum)

【讨论】:

  • 但是这个函数返回 185 值,我的预期答案是 225。为什么我没有得到正确的 crc?
  • @Dhasal:如上所述,您必须更新正在运行的校验和,而不是分别为每个字节计算它:for item in bytes { checkSum = calculateCheckSum(crc: checkSum, byteValue: UInt8(item)) } ; print(checkSum)
  • @MartinR 好收获
【解决方案2】:

我刚刚从 this github link 进行了扩展,它可以获取 CRC32 校验和以防万一有人需要它。

extension Data {
public func checksum() -> UInt32 {
    let table: [UInt32] = {
        (0...255).map { i -> UInt32 in
            (0..<8).reduce(UInt32(i), { c, _ in
                (c % 2 == 0) ? (c >> 1) : (0xEDB88320 ^ (c >> 1))
            })
        }
    }()
    return ~(self.bytes.reduce(~UInt32(0), { crc, byte in
        (crc >> 8) ^ table[(Int(crc) ^ Int(byte)) & 0xFF]
    }))
} }

【讨论】:

  • 感谢您的解决方案。我们不能再使用 Data.bytes 了。这是我更新后的代码: return ~( self.withUnsafeBytes({ pointers in pointers.reduce(~UInt32(0), { crc, byte in (crc >> 8) ^ table[(Int(crc) ^ Int(byte) ) & 0xFF] }) }) )
猜你喜欢
  • 2017-08-13
  • 2010-09-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多