Go 两个';s补码与fmt.Printf
所以计算机使用2的补码在内部表示有符号整数。即,-5表示为^5+1=“1111 1011” 但是,尝试打印二进制表示,例如以下代码:Go 两个';s补码与fmt.Printf,go,Go,所以计算机使用2的补码在内部表示有符号整数。即,-5表示为^5+1=“1111 1011” 但是,尝试打印二进制表示,例如以下代码: var i int8 = -5 fmt.Printf("%b", i) 输出-101。不完全是我所期望的。格式是不同的还是根本不使用二的补码 有趣的是,转换为无符号整数会产生“正确”的位模式: var u uint8 = uint(i) fmt.Printf("%b", u) 输出为11111 011-正好是-5的2s补码 因此,在我看来,该值在内部是真正使用
var i int8 = -5
fmt.Printf("%b", i)
输出-101
。不完全是我所期望的。格式是不同的还是根本不使用二的补码
有趣的是,转换为无符号整数会产生“正确”的位模式:
var u uint8 = uint(i)
fmt.Printf("%b", u)
输出为11111 011
-正好是-5
的2s补码
因此,在我看来,该值在内部是真正使用二的补码的值,但格式是打印无符号的5
并在-
前面加上前缀
有人能澄清一下吗?我相信答案在于
fmt
模块如何格式化二进制数,而不是内部格式
如果您看一看,函数执行的第一个操作之一是将负有符号整数转换为正整数:
165 negative := signedness == signed && a < 0
166 if negative {
167 a = -a
168 }
165负:=signedness==signed&&a<0
166如果是负数{
167A=-a
168 }
然后在输出的字符串前面添加-
逻辑
IOW-101
实际上是以二进制形式附加到5
之后的-
注意:
fmt.integer
是从pp.fmtInt64
中调用的,它本身是从同一函数中的pp.printArg
中调用的。必须使用不安全指针以二进制格式正确表示负数
package main
import (
"fmt"
"strconv"
"unsafe"
)
func bInt8(n int8) string {
return strconv.FormatUint(uint64(*(*uint8)(unsafe.Pointer(&n))), 2)
}
func main() {
fmt.Println(bInt8(-5))
}
输出
11111011
我不知道为什么有人会认为这很“奇怪”。不管你用什么基数,负数仍然是负数。如果你在8、12或16垒要求,我也会期待同样的结果。我没说奇怪。我只是试着理解2s补码,结果并不是我所期望的。我不认为你真的可以通过玩用高级语言编写的数字格式函数来理解2的补码。你有什么建议?