【问题标题】:Negative of UInt8UInt8 的负数
【发布时间】:2017-04-03 15:20:21
【问题描述】:

我在 Objective-C 中有这段代码,我想用 Java 编写它。然而,(-(crc & 1)) 的声明给我带来了问题。经过一些谷歌搜索后,似乎无符号的负数通常没有很好地定义。不过我不太明白。也许知道 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);
}

在 cmets 的帮助下解决的代码。好像是我找错地方了。

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

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

【问题讨论】:

  • “无符号的负数通常没有很好的定义” - 定义得很好:一个 unsigned 整数不能是负数。就是这样。
  • 是的,我明白了。所以问题是这个程序实际上在做什么的等价物。因为它正在工作。
  • 我们不是代码翻译服务。
  • 如果你能告诉我它的作用,我也很高兴我自己编程。
  • -(crc & 1) 技巧仅在设置了底部位时才用于与 0xedb88320 进行异或。在 Java 中也是如此。

标签: java objective-c crc


【解决方案1】:

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

对于没有无符号整数的 Java,您需要解决两件事。首先是右移需要是逻辑右移>>>。这样可以避免在向下移位时复制符号位,而是移入零位。其次,您需要防止字符被签名扩展为int,因此byte(在Java 中需要不同的名称)需要与0xff 进行与运算。所以:

crc ^= octet & 0xff;

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

【讨论】:

    【解决方案2】:

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

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

    因此,表达式-(crc & 1) 的计算结果为0-10 的位模式全为零,-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 中右移,因为src 被定义为无符号 em> (signed 整数的右移是(Objective-)C 中的“实现定义”)。

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

    把所有这些放在一起,你的整个表达式 (crc >> 1) ^ (0xedb88320ul & (-(crc & 1))) 有条件地 xors 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 还提供了>>> 运算符来执行逻辑无符号右移。

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

    HTH

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-08
      • 2017-03-11
      • 1970-01-01
      • 1970-01-01
      • 2019-12-28
      相关资源
      最近更新 更多