5

我正在将 C++ 程序转换为 Java,并完全陷入了以下让我大吃一惊的方法。您能解释一下这种方法的作用吗?

long TSBCA::GetSignedValue(const NDataString &value)
    {
       static NDataString s;    
       s = value;

       long multiplier(1);
       size_t len(s.Len());
       if (len != 0)
       {
          if (s[0] >= (char)0xB0 && s[0] <= (char)0xB9)
          {
             s[0] &= 0x7F; //Bit Pattern: 0111 1111
             multiplier = -1;
          }
          else if (s[len - 1] >= (char)0xB0 && s[len - 1] <= (char)0xB9)
          {
             s[len - 1] &= 0x7F; //Bit Pattern: 0111 1111
             multiplier = -1;
          }
          else
             multiplier = 1;
       }
       else
          multiplier = 1;
       return s.ToLong() * multiplier;
    }

编辑:

我的初始 Java 版本:

private long getSignedValue(final String value){

       byte[] bytes = value.getBytes();
       int length = bytes.length;
       long multiplier = 1L;

       if (bytes.length > 0){
          if (bytes[0] >= (char)0xB0 && bytes[0] <= (char)0xB9){


             bytes[0] &= 0x7F; //Bit Pattern: 0111 1111
             multiplier = -1;
          }
          else if (bytes[length - 1] >= (char)0xB0 && bytes[length - 1] <= (char)0xB9)
          {
              bytes[length - 1] &= 0x7F; //Bit Pattern: 0111 1111
             multiplier = -1;
          }
          else
             multiplier = 1;
       }
       else
          multiplier = 1;
       return Long.parseLong(Arrays.toString(bytes))* multiplier;
}

我做对了吗?

4

3 回答 3

1

它需要一个字节字符串(即不是文本)并将其转换为很长的时间。它依赖于许多实现特定的东西,并且看起来很糟糕:它从两个不同的地方提取符号位。另一个问题是不必要的不​​可重入(由静态变量引起)。

于 2009-12-01T21:20:34.677 回答
1
s[0] &= 0x7F;

表示位和s[0]十六进制7F或换句话说,从字节值中去除符号位。与 相同s[len-1],所以它:

  • 接受一个数字字符串,其中第一个或最后一个数字添加了一个符号位(0x30- 0x39== '0'-'9'0xB0-0xB90x80位设置的范围相同。)
  • 去掉那个符号位,记住它是乘数
  • 使用乘数解释数字字符串参数以设置符号
  • 返回该值

编辑

查看您的代码使我有以下评论:

  • 它没有按预期工作,请务必为新代码编写一些 JUnit 测试,以检查它们是否符合您的预期
  • 将幻数放在单独的常量中
  • byte与字节比较时使用常量(符号问题)
  • 悬空的其他人应该得到大括号,在这种情况下是不需要的
  • 用于new String(byte[])重建字符串,而不是 Arrays 实用程序类。

这将我引向这个版本:

// Bit Pattern: 0111 1111
private static final int BYTE_7F = 0x7F;

// '0' with sign bit set
private static final byte BYTE_NEGATIVE_0 = (byte) 0xB0;

// '9' with sign bit set
private static final byte BYTE_NEGATIVE_9 = (byte) 0xB9;


private long getSignedValue(String value) {

    byte[] bytes = value.getBytes();
    final int length = bytes.length;
    long multiplier = 1;

    if (0 < length) {
        if (bytes[0] >= BYTE_NEGATIVE_0 && bytes[0] <= BYTE_NEGATIVE_9) {

            bytes[0] &= BYTE_7F; 
            multiplier = -1;

        } else if (bytes[length - 1] >= BYTE_NEGATIVE_0 && bytes[length - 1] <= BYTE_NEGATIVE_9) {
            bytes[length - 1] &= BYTE_7F;
            multiplier = -1;
        }
    }

    return Long.parseLong(new String(bytes)) * multiplier;
}

您仍然需要注意添加正确的注释并更新常量名称以使它们与您的文档术语保持一致。

于 2009-12-01T21:23:03.757 回答
0

看起来它正在测试一些奇怪的符号版本(正面或负面)。如果第一个或最后一个(但最好是第一个)字符在0xB0and之间0xB9,则删除它是哪个字符的最高位(使其介于0x30and之间0x39,数字'0''9')。然后返回带有负号的数字,就像普通人知道的那样。

于 2009-12-01T21:24:42.653 回答