【问题标题】:Performing bitwise left shifts on "signed" data in Java -- better to move to JNI?在 Java 中对“签名”数据执行按位左移 - 更好地迁移到 JNI?
【发布时间】:2010-11-16 21:43:44
【问题描述】:

在过去的一周里,我一直在询问有关十六进制和按位操作(这里和其他地方)的问题,试图围绕它们在 Java 中的表示进行思考。经过多次谷歌搜索和懊恼,我必须最后一次问如何对应该是无符号但在 Java 中表示为有符号的位执行逻辑算术。

好的:我正在将 C# 程序移植到 Java。该程序处理位图操作,因此应用程序中的大部分数据都表示为 byte,一个无符号的 8 位整数。有许多建议改为在 Java 中使用 short 数据类型,以便“模仿”尽可能接近无符号 8 字节整数。

我不相信这对我来说是可能的,因为 C# 代码正在对我的字节数据执行各种移位和 AND 操作。比如data是一个字节数组,而这块代码存在于C#中:

int cmdtype = data[pos] >> 5;
int len = (data[pos] & 0x1F) + 1;

if (cmdtype == 7)
{
    cmdtype = (data[pos] & 0x1C) >> 2;
    len = ((data[pos] & 3) << 8) + data[pos + 1] + 1;
    pos++;
}

data 转换为short 并完成它以使其在Java 中工作并不是一件简单的事情。就逻辑而言,我的数据保持为 8 位无符号的要求很重要; 16 位无符号会像上面那样搞砸数学。我在这里吗?确实,在之前在 Java 中使用 0XFFchar 进行“假铸造”byte 并且没有得到正确的结果之后,恐怕我走到了死胡同。

现在,在代码的另一部分,我正在执行一些位图像素操作。由于这是一个长期运行的过程,我决定通过 JNI 调用本机代码。我最近意识到,在那里我可以使用 uint8_t 数据类型并获得最接近 C# byte 数据类型的表示。

解决方案是让我的所有数据相关功能都在 JNI 中运行吗?这似乎非常低效,无论是重写还是执行。是在 Java 中重做数学的解决方案,所以逻辑保持不变?这似乎是对的,但有可能诱发动脉瘤,更不用说数学错误了。

我感谢任何和所有建议。

【问题讨论】:

  • 您能否在代码 sn-p 的每个步骤中添加 cmets 来指示 C# 的作用与 Java 的作用?我认为我无法弄清楚代码中您可能会发现问题的所有地方。
  • 我没有任何可以归类为答案的东西,但是如果您正在做很多事情,我建议使用 JNI 编写一个简单的类来执行此操作,而不是进行大量转换.这会损害性能、可调试性和可读性。无论如何,在将所有内容都转换为 JNI 之前,我仍然会分析代码。专注于最需要的领域。
  • @John 我不建议在 JNI 中重做这一切——我只是想知道这是否是一个可行的解决方案。

标签: c# java java-native-interface byte bit-manipulation


【解决方案1】:

请注意:您不能直接转换为short,因为负数将在逻辑上扩展。

也就是说,字节1111 1101 (-5) 在直接转换为short 时会得到1111 1111 1111 1101 (-5),而不是0000 0000 1111 1101 (253)。投射时必须使用 AND 操作删除前导:

short shortValue = ((short)(byteValue)) & 0xFF;

我知道像这样的复杂位操作是可能的,因为我在处理带有 Java Swing 应用程序的遗留二进制消息传递协议时已经完成了这件事。我强烈建议以某种方式将其抽象出来,以便您只需处理一次。这是否意味着将您的“字节”包装在一个类中以将它们存储为短裤并处理转换操作,或者定义一个静态实用程序来一次性完成转换和位操作,以便您始终存储字节。

【讨论】:

  • 我觉得我的大脑已经炸了。如果我进行翻转和演员表,我的按位数学会保持不变吗?正如我之前所说,我使用您描述的确切技术“假铸造”,只使用 char 代替。
【解决方案2】:

Java 有 &gt;&gt;&gt;(注意三个 ">" 字符,而不仅仅是两个)无符号右移运算符。这应该至少保持 C# 样式右移(高位清零,而不是符号填充)。

就转换为“short”而言,C# 将所有这些字节转换为 32 位整数,然后再进行移位。唯一的技巧是,C# 执行无符号强制转换(只是用 0 填充高 24 位,而不管第 7 位的值如何)。如果您确实在 Java 中转换为 short,您应该只能说:

short shortCast = ( (short)byteVal ) & 0xff;
short shiftedShortCast = shortCast << whatever;

【讨论】:

  • C# 确实会转换为int,但它也有无符号类型的概念,这会阻止前导类型扩展为负数。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-05
  • 2021-01-13
  • 1970-01-01
相关资源
最近更新 更多