二进制补码和 fmt.Printf

所以计算机使用二进制补码在内部表示有符号整数。即,-5 表示为 ^5 + 1 = "1111 1011"。


但是,尝试打印二进制表示,例如以下代码:


var i int8 = -5

fmt.Printf("%b", i)

输出-101。不完全是我所期望的。格式是不同的还是根本不使用二进制补码?


有趣的是,转换为 unsigned int 会产生“正确”的位模式:


var u uint8 = uint(i)

fmt.Printf("%b", u)

输出是11111011- 正好是 的 2s 补码-5。


所以在我看来,这个值在内部实际上是使用二进制补码,但格式是打印无符号5并在前面加上-.


有人可以澄清一下吗?


慕姐8265434
浏览 133回答 3
3回答

慕娘9325324

我相信答案在于fmt模块如何格式化二进制数,而不是内部格式。如果您看一下fmt.integer,该函数首先执行的操作之一是将带负号的整数转换为正整数:&nbsp; &nbsp;165&nbsp; &nbsp; &nbsp; negative := signedness == signed && a < 0&nbsp; &nbsp;166&nbsp; &nbsp; &nbsp; if negative {&nbsp; &nbsp;167&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; a = -a&nbsp; &nbsp;168&nbsp; &nbsp; &nbsp; }然后在此处-输出的字符串前面附加逻辑。IOW-101确实以二进制形式-附加。5注意:在print.gofmt.integer中调用,它本身在同一个函数中调用。pp.fmtInt64pp.printArg

qq_笑_17

这是一种不使用的方法unsafe:package mainimport (&nbsp; &nbsp;"fmt"&nbsp; &nbsp;"math/bits")func unsigned8(x uint8) []byte {&nbsp; &nbsp;b := make([]byte, 8)&nbsp; &nbsp;for i := range b {&nbsp; &nbsp; &nbsp; if bits.LeadingZeros8(x) == 0 {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;b[i] = 1&nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; x = bits.RotateLeft8(x, 1)&nbsp; &nbsp;}&nbsp; &nbsp;return b}func signed8(x int8) []byte {&nbsp; &nbsp;return unsigned8(uint8(x))}func main() {&nbsp; &nbsp;b := signed8(-5)&nbsp; &nbsp;fmt.Println(b) // [1 1 1 1 1 0 1 1]}在这种情况下,您也可以使用[8]byte,但如果您有一个正整数并且想要修剪前导零,则上述方法会更好。https://golang.org/pkg/math/bits#RotateLeft

犯罪嫌疑人X

必须使用不安全指针才能正确表示二进制格式的负数。package mainimport (&nbsp; &nbsp; "fmt"&nbsp; &nbsp; "strconv"&nbsp; &nbsp; "unsafe")func bInt8(n int8) string {&nbsp; &nbsp; return strconv.FormatUint(uint64(*(*uint8)(unsafe.Pointer(&n))), 2)}func main() {&nbsp; &nbsp; fmt.Println(bInt8(-5))}输出11111011
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go