如何将整数转换为带符号的十六进制补码:

huangapple go评论71阅读模式
英文:

how to convert integer to hex signed 2's complement:

问题

以下是翻译的内容:

相当基础的东西,我确信,但位操作并不是我的强项。

因此,对于一些内部计算,我正在尝试将给定的输入(约束是它肯定是一个整数字符串)转换为其十六进制等价物,让我困惑的是如何获得十六进制有符号的二进制补码:

我的新手代码:

private String toHex(String arg, boolean isAllInt) {
    String hexVal = null;
    log.info("arg {}, isAllInt {}", arg, isAllInt);
    if (isAllInt) {
        int intVal = Integer.parseInt(arg);
        hexVal = Integer.toHexString(intVal);
        // 一些魔法将这个 hexVal 转换为它的二进制补码
    } else {
        hexVal = String.format("%040x", new BigInteger(1, arg.getBytes(StandardCharsets.UTF_8)));
    }
    log.info("str {} hex {}", arg, hexVal);
    return hexVal;
}

输入:00001
输出:1
期望输出:0001

输入:00216
输出:D8
期望输出:00D8

00216

输入:1192633166
输出:4716234E
期望输出:4716234E

欢迎使用任何预定义库或其他有用的指针!

英文:

Pretty basic stuff i am sure but bits are not my forte.

So for some internal calculation i am trying to convert a given input ( constraint is that it would be a integer string for sure) into its hex equivalent, what stumped me is on how to get
Hex signed 2's complement:

My noob code:

   private String toHex(String arg, boolean isAllInt) {
        String hexVal = null;
        log.info("arg {}, isAllInt {}", arg, isAllInt);
        if (isAllInt) {
            int intVal = Integer.parseInt(arg);
            hexVal = Integer.toHexString(intVal);
            // some magic to convert this hexVal to its 2's compliment
        } else {
            hexVal = String.format("%040x", new BigInteger(1, arg.getBytes(StandardCharsets.UTF_8)));
        }
        log.info("str {} hex {}", arg, hexVal);
        return hexVal;
    }

Input: 00001 <br />
Output: 1<br />
Expected Output: 0001<br />

Input: 00216 <br />
Output: D8<br />
Expected Output: 00D8<br />

00216

Input: 1192633166<br />
Output: 4716234E<br />
Expected Output: 4716234E<br />

any predefined library is much welcome or any other useful pointers!

答案1

得分: 2

为了将十六进制数字填充到4位或8位,可以执行以下操作:

int intVal = Integer.parseInt(arg);
if (intVal >= 0 && intVal <= 0xffff) {
     hexVal = String.format("%04x", intVal);
} else {
     hexVal = String.format("%08x", intVal);
}

有关格式字符串的工作原理,请参阅Java文档

英文:

So to pad the hex digits up to either 4 digits or 8 digits, do:

int intVal = Integer.parseInt(arg);
if (intVal &gt;= 0 &amp;&amp; intVal &lt;= 0xffff) {
     hexVal = String.format(&quot;%04x&quot;, intVal);
} else {
     hexVal = String.format(&quot;%08x&quot;, intVal);
}

See Java documentation on how the format strings work.

答案2

得分: 1

回答二进制补码的部分。

二进制补码表示法

二进制补码是一种约定,用于表示带符号整数,例如16位(在早期,不同的处理器使用不同的表示法,例如一的补码或符号-大小表示法)。

正数和零的表示如下:

  • 0 表示为 0000 0000 0000 0000 或十六进制 0000
  • 1 表示为 0000 0000 0000 0001 或十六进制 0001
  • 2 表示为 0000 0000 0000 0010 或十六进制 0002
  • 3 表示为 0000 0000 0000 0011 或十六进制 0003
  • 4 表示为 0000 0000 0000 0100 或十六进制 0004

负数通过添加 1 0000 0000 0000 0000 来表示:

  • -1 表示为 1111 1111 1111 1111 或十六进制 ffff
  • -2 表示为 1111 1111 1111 1110 或十六进制 fffe
  • -3 表示为 1111 1111 1111 1101 或十六进制 fffd

这等价于:获取正数表示,翻转所有位,然后加 1。

对于负数,最高位始终为1。这是机器区分正负数的方式。

当今所有使用的处理器都基于二进制补码表示进行整数运算,因此通常无需进行特殊处理。所有的Java数据类型,如byteshortintlong,都被定义为二进制补码表示的带符号数。

在您的评论中,您写道

> 二补数是原始值的负数的十六进制表示

这有点混淆了概念。二进制补码基本上是在位模式上定义的,从这些位模式中可以很好地分组为十六进制数字。二进制补码是关于将负值表示为位模式,但从您的问题和评论中可以看出,您不期望负值,因此不需要关注二进制补码。

十六进制字符串

要将带符号的值表示为十六进制字符串,Java(以及大多数其他语言/环境)只需查看位模式,忽略其正/负解释,这意味着例如 -30(1111 1111 1110 0010)不会显示为带有减号的“-1e”,而是显示为“ffe2”。

因此,负值将始终被转换为具有值大小的最大长度的字符串(16位,32位,64位分别为4、8或16个十六进制数字),因为最高位将为1,导致最左边的十六进制数字肯定不为零。因此,对于负值,不需要进行任何填充。

小的正值在其十六进制表示中会有前导零,Java的toHexString()方法会将它们去除,因此1(0000 0000 0000 0001)变为“1”而不是“0001”。这就是为什么例如format(&quot;%04x&quot;, ...)(在@nos的答案中)很有用。

英文:

Answering the two's complement aspect.

Two's Complement Representation

Two's complement is an agreement how to represent signed integral numbers in e.g. 16 bits (in olden times, different representations have been used by various processors, e.g. one's complement or sign-magnitude).

Positive numbers and zero are represented as expected:

  • 0 is 0000 0000 0000 0000 or hex 0000
  • 1 is 0000 0000 0000 0001 or hex 0001
  • 2 is 0000 0000 0000 0010 or hex 0002
  • 3 is 0000 0000 0000 0011 or hex 0003
  • 4 is 0000 0000 0000 0100 or hex 0004

Negative numbers are represented by adding 1 0000 0000 0000 0000 to them, giving:

  • -1 is 1111 1111 1111 1111 or hex ffff
  • -2 is 1111 1111 1111 1110 or hex fffe
  • -3 is 1111 1111 1111 1101 or hex fffd

This is equivalent to: take the positive representation, flip all bits, and add 1.

For negative numbers, the highest bit is always 1. And that's how the machine distinguishes positive and negative numbers.

All processors in use today do their integer arithmetic based on two's complement representation, so there's typically no need to do special tricks. All the Java datatypes like byte, short, int, and long are defined to be signed numbers in two's complement representation.

In a comment you wrote

> 2's compliment is hex of negative of original value

That mixes up the concepts a bit. Two's complement is basically defined on bit patterns, and groups of 4 bits from these bit patterns can nicely be written as hex digits. Two's complement is about representing negative values as bit patterns, but from your question and comments I read that you don't expect negative values, so two's complement shouldn't concern you.

Hex Strings

To represent signed values as hex strings, Java (and most other languages / environments) simply looks at the bit patterns, ignoring their positive / negative interpretation, meaning that e.g. -30 (1111 1111 1110 0010) does not get shown as "-1e" with a minus sign, but as "ffe2".

Because of this, negative values will always get translated to a string with maximum length according to the value's size (16 bits, 32 bits, 64 bits giving 4, 8, or 16 hex digits), because the highest bit will be 1, resulting in a leading hex digit surely not being zero. So for negative values, there's no need to do any padding.

Small positive values will have leading zeros in their hex representation, and Java's toHexString() method suppresses them, so 1 (0000 0000 0000 0001) becomes "1" and not "0001". That's why e.g. format(&quot;%04x&quot;, ...), as in @nos's answer, is useful.

huangapple
  • 本文由 发表于 2020年10月8日 14:31:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/64256945.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定