UInt8 的负数

Negative of UInt8

我在Objective-C中有这段代码,我想在Java中编写它。但是,(-(crc & 1)) 语句给我带来了问题。经过一番谷歌搜索后,似乎 unsigned 的负数通常没有明确定义。虽然我不太明白。也许知道 CRC 的人可以告诉我 Java 中的等价物是什么。

我需要一个完全等效的方法作为一个设备,这个 Objective-C 代码检查我计算的 crc 与它自己计算的。

+ (UInt32) crc32:(UInt32) crc ofByte: (UInt8) byte
{
    int8_t i;
    crc = crc ^ byte;
    for (i = 7; i >= 0; i--)
    {
        crc = (crc >> 1) ^ (0xedb88320ul & (-(crc & 1)));
    }
    return(crc);
}

在注释的帮助下解决了代码。好像搜错地方了

private void addByteToCRC(byte oneByte) {
    crc ^= oneByte & 0xFF;
    for (int i = 7; i >= 0; i--)
    {
        crc = (crc >>> 1) ^ (0xedb88320 & (-(crc & 1)));
    }
}

两个校验和都以 0xFFFFFFFF 的 crc 值开始。

(Objective-)C 和 Java 之间存在一些差异,但据推测您可能发现了错误的问题。 Java 没有无符号整数类型。然而,它确实有按位运算符将整数视为只是位串,并且 Java 的更高版本确实有无符号 运算符 ,当应用于整数时,它们对底层位模式进行操作作为尽管它们代表无符号值。

表达式 crc & 1 将产生 01 的结果,具体取决于 crc 是偶数还是奇数。

因此,表达式 -(crc & 1) 的计算结果为 0-10 的位模式全为 0,而 -1 的位模式全为 1 - 后者在 (Objective-)C 中为真,而不管整数的底层表示为 1 或 2 的补码, 请参阅 Is it safe to use -1 to set all bits to true? 了解解释。

因此,表达式 0xedb88320ul & (-(crc & 1)) 的计算结果为 00xedb88320

表达式crc >> 1逻辑,或无符号,向右移(Objective-) C as src 被定义为 unsignedsigned 整数的右移是 "implementation defined" in (Objective -)C)。

任何 x 的表达式 x ^ 0 的计算结果为 x

把它们放在一起,你的整个表达式 (crc >> 1) ^ (0xedb88320ul & (-(crc & 1))) 有条件地将 crc >> 10xedb88320 进行异或运算,不管 crc 是奇数还是偶数。

现在您只需要在 Java 中重现相同的行为。

Java 对 int (JLS: Primitive Types and Values) 使用 32 位 2 的补码整数,并提供将它们视为位串的位运算符。

十六进制常量刚好 0xedb88320 并且具有 int(32 位)类型。

因此,表达式 -(crc & 1) 的计算结果与 (Objective-)C 中的一样。

然而,表达式 crc >> 1 而不是 与 (Objective-)C 中的计算结果相同。在 Java 中,>> 是一个 算术 右移,它在移位期间复制符号位。此选择源于 Java 使用签名类型。幸运的是 Java 还提供了 >>> 运算符来执行 logical,或 unsigned,右移 [=41] =]

所以我猜你可能在转换中发现了错误的问题,你需要使用 >>> 运算符。

HTH

-(crc & 1) 工作正常,不是你的问题。它所做的是将 crc 的低位复制到所有位,因为在二进制补码表示中,–1 是全 1。

对于没有无符号整数的 Java,您需要解决两件事。首先是右移需要是逻辑右移,>>>。这避免了在向下移动时复制符号位,而是移入零位。其次,您需要防止字符被符号扩展为 int,因此 byte(在 Java 中需要不同的名称)需要与 [=17= 相加].所以:

crc ^= octet & 0xff;

crc = (crc >>> 1) ^ (0xedb88320ul & (-(crc & 1)));