【问题标题】:Kotlin: Convert Hex String to signed integer via signed 2's complement?Kotlin:通过有符号 2 的补码将十六进制字符串转换为有符号整数?
【发布时间】:2021-07-13 21:04:13
【问题描述】:

长话短说,我正在尝试将十六进制值字符串转换为有符号 2 的补码整数。我能够在 Swift 中的一行代码中做到这一点,但由于某种原因,我在 Kotlin 中找不到类似的东西。 String.ToInt 或 String.ToUInt 只是给出直接以 16 为基数到以 10 为基数的转换。这适用于某些正值,但不适用于任何负数。

我怎么知道我想要带符号的 2 的补码?我使用了this online converter,根据它的输出,我想要的是带符号 2 的补码的小数,而不是简单的以 16 为基数到以 10 为基数的直接转换,这种转换很容易手动完成。

因此,“FFD6”应该变为 -42(正确,在 Swift 和 C# 中确认),“002A”应该转换为 42。

我将不胜感激任何帮助,甚至任何关于在哪里寻找的线索。因为是的,我已经搜索过了,我用谷歌搜索了很多问题,但没有找到好的答案。

我实际上尝试编写自己的代码来执行有符号 2 的补码,但到目前为止它并没有给我正确的答案,我很茫然。我真的希望有一个内置的命令来代替它;我觉得如果其他语言也有 Kotlin 应该具备的能力。

【问题讨论】:

    标签: kotlin type-conversion


    【解决方案1】:

    对于 2 的补码,你需要知道类型有多大。

    您的“FFD6”和“002A”示例都有 4 个十六进制数字(即 2 个字节)。这与 Kotlin Short 的大小相同。因此,在这种情况下,一个简单的解决方案是将十六进制解析为Int,然后将其转换为Short。 (您不能将其直接转换为 Short,因为这会给负数带来超出范围的错误。)

    "FFD6".toInt(16).toShort() // gives -42
    
    "002A".toInt(16).toShort() // gives 42
    

    (如果需要,您可以随后转换回 Int。)

    您可以类似地将 8 位(4 字节)值处理为 Ints,将 2 位(1 字节)值处理为 Bytes。

    对于其他尺寸,您需要进行一些位操作。基于this answer for Java,如果你有例如一个 3 位的十六进制数字,你可以这样做:

    ("FD6".toInt(16) xor 0x800) - 0x800 // gives -42
    

    (这里0x800 是设置了最高位(即符号位)的三位数字。  您可以将0x80000 用于五位数字,依此类推。  此外,对于 9-16 位数字,您需要以 Long 而不是 Int 开头。  如果您需要 >16 位数字,它也不适合 Long,因此您需要一个任意精度的库处理十六进制...)

    【讨论】:

    • 谢谢!因此,如果我有 0xFFD6,我将无法执行 "0xFFD6".toInt(16).toShort() 来获得 -42,对吗?我可以做 "0xFFD6".toInt(16).toLong() 吗?
    • 试试看!您可以运行kotlinc,并将程序和表达式直接输入到 REPL。输入 `"0xFFD6".toInt(16).toShort()` 会产生 NumberFormatException,因为它无法解析 0x。 (我不知道有任何内置函数可以。)  并且"FFD6".toInt(16).toLong() 没有做你想做的事(给出 65494);这是对Short 的截断来整理符号。
    猜你喜欢
    • 1970-01-01
    • 2021-01-23
    • 2021-11-05
    • 2019-05-03
    • 2020-11-26
    • 2012-08-29
    • 2011-04-11
    相关资源
    最近更新 更多