将一个3字节的切片和有符号整数类型进行转换

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

Converting between a 3-byte slice and signed integer type

问题

我有一个由3个字节组成的切片(按照小端序排列),表示一个有符号整数,我想将其转换为任何整数类型,最好是int32,然后再转回原来的形式。

b := []byte{0x01, 0x00, 0x80}

我尝试使用big.Int来实现,但似乎它的SetBytes()Bytes()方法只适用于无符号整数类型,而不管big.Int实例也可以存储有符号整数类型。

以下是我尝试实现的Python等效代码:

b = b"\x01\x00\x80"
i = int.from_bytes(b, "little", signed=True)
b_again = int.to_bytes(i, "little", signed=True)

编辑:这个问题不是https://stackoverflow.com/questions/34701187/go-byte-to-little-big-endian-signed-integer-or-float的重复。我尝试了那里的答案,但结果并不如预期。请参考我的第一个评论。

英文:

I have a slice consisting of 3 bytes (ordered in LE) that is representing a signed integer, and I want to convert it to any of the integer types, preferably int32, and then back to itself.

b := []byte{0x01, 0x00, 0x80}

I tried to do that using big.Int, but it seemed like its SetBytes() and Bytes() methods only work for unsigned integer types, regardless of that a big.Int instance can also store signed integer types.

Here is a Python equivalent of what I’m trying to do:

b = b"\x01\x00\x80"
i = int.from_bytes(b, "little", signed=True)
b_again = int.to_bytes("little", signed=True)

Edit: This question is not a duplicate of https://stackoverflow.com/questions/34701187/go-byte-to-little-big-endian-signed-integer-or-float. I have tried applying the answers there, but their results weren’t expected. See my first comment.

答案1

得分: 3

我有一个由3个字节组成的切片(按照小端序排列),表示一个有符号整数,我想将其转换为任何整数类型,最好是int32,然后再转回原来的类型。

package main

import "fmt"

func ByteLE3ToInt24(b []byte) int32 {
    i := uint32(b[0])<<8 | uint32(b[1])<<16 | uint32(b[2])<<24
    return int32(i) >> 8
}

func Int24ToByteLE3(i int32) []byte {
    return []byte{byte(i), byte(i >> 8), byte(i >> 16)}
}

func main() {
    b := []byte{0x01, 0x00, 0x80} // 负数
    fmt.Println(b)
    fmt.Println(ByteLE3ToInt24(b))
    fmt.Println(Int24ToByteLE3(ByteLE3ToInt24(b)))
    fmt.Println()
    b = []byte{0x01, 0x00, 0x00} // 正数
    fmt.Println(b)
    fmt.Println(ByteLE3ToInt24(b))
    fmt.Println(Int24ToByteLE3(ByteLE3ToInt24(b)))
}

输出结果:

[1 0 128]
-8388607
[1 0 128]

[1 0 0]
1
[1 0 0]

你可以在这里查看代码和运行结果:https://go.dev/play/p/tI8E2kSXopZ

英文:

> I have a slice consisting of 3 bytes (ordered in LE) that is representing a signed integer, and I want to convert it to any of the integer types, preferably int32, and then back to itself.


package main

import &quot;fmt&quot;

func ByteLE3ToInt24(b []byte) int32 {
	i := uint32(b[0])&lt;&lt;8 | uint32(b[1])&lt;&lt;16 | uint32(b[2])&lt;&lt;24
	return int32(i) &gt;&gt; 8
}

func Int24ToByteLE3(i int32) []byte {
	return []byte{byte(i), byte(i &gt;&gt; 8), byte(i &gt;&gt; 16)}
}

func main() {
	b := []byte{0x01, 0x00, 0x80} // Negative
	fmt.Println(b)
	fmt.Println(ByteLE3ToInt24(b))
	fmt.Println(Int24ToByteLE3(ByteLE3ToInt24(b)))
	fmt.Println()
	b = []byte{0x01, 0x00, 0x00} // Positive
	fmt.Println(b)
	fmt.Println(ByteLE3ToInt24(b))
	fmt.Println(Int24ToByteLE3(ByteLE3ToInt24(b)))
}

https://go.dev/play/p/tI8E2kSXopZ

[1 0 128]
-8388607
[1 0 128]

[1 0 0]
1
[1 0 0]

答案2

得分: -1

Little-Endian(小端序)意味着数字0x01020304被编码为字节序列[]byte{4, 3, 2, 1}

你的示例数字有三个字节,所以我假设你的意思是0x00010080(左侧填充一个零字节)。

有一个encoding/binary.ByteOrder类型,它有两个实例LittleEndianBigEndian,提供了转换为字节和从字节转换的函数:

package main

import (
	"encoding/binary"
	"fmt"
)

func main() {
	var b [4]byte
	binary.LittleEndian.PutUint32(b[:], 0x00010080)
	i32 := int32(binary.LittleEndian.Uint32(b[:]))
	fmt.Println(b)   // 输出 [128 0 1 0]。
	fmt.Println(i32) // 输出 65664(等于0x00010080)。
}
英文:

Little-Endian means that the number 0x01020304 is encoded as the byte squence []byte{4, 3, 2, 1}.

Your example number has three bytes, so I assume that you mean 0x00010080 (left-filled with a zero-byte).

There is a type encoding/binary.ByteOrder with the two instances LittleEndian and BigEndian which provide functions to convert to and from bytes:

package main

import (
	&quot;encoding/binary&quot;
	&quot;fmt&quot;
)

func main() {
	var b [4]byte
	binary.LittleEndian.PutUint32(b[:], 0x00010080)
	i32 := int32(binary.LittleEndian.Uint32(b[:]))
	fmt.Println(b)   // Prints [128 0 1 0].
	fmt.Println(i32) // Prints 65664 (which is 0x00010080).
}

huangapple
  • 本文由 发表于 2023年7月24日 19:23:17
  • 转载请务必保留本文链接:https://go.coder-hub.com/76753977.html
匿名

发表评论

匿名网友

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

确定