因此,计算机使用二进制补码来内部表示有符号整数。即,-5表示为^ 5 + 1 =“1111 1011”。
但是,尝试打印二进制表示,例如以下代码:
var i int8 = -5
fmt.Printf("%b", i)
输出-101
。不是我所期待的。格式是不同还是不使用Two的补码?
有趣的是,转换为unsigned int会产生“正确”的位模式:
var u uint8 = uint(i)
fmt.Printf("%b", u)
输出为11111011
- 恰好是-5
的2s补码。
所以在我看来,值在内部实际上是使用二进制补码,但格式化是打印无符号5
并且前置-
。
有人可以澄清这个吗?
答案 0 :(得分:8)
我认为答案在于fmt
模块如何格式化二进制数,而不是内部格式。
如果你看一下fmt.integer
,该函数的第一个动作之一是将负有符号整数转换为正整数:
165 negative := signedness == signed && a < 0
166 if negative {
167 a = -a
168 }
然后将-
添加到输出here的字符串前面的逻辑。
IOW -101
确实-
以二进制方式附加到5
。
注意:fmt.integer
来自print.go中的pp.fmtInt64
,pp.printArg
在同一个函数中从top-a
调用。
答案 1 :(得分:0)
必须使用不安全的指针来以二进制格式正确表示负数。
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
答案 2 :(得分:0)
这是一个不使用 unsafe
的方法:
package main
import (
"fmt"
"math/bits"
)
func unsigned8(x uint8) []byte {
b := make([]byte, 8)
for i := range b {
if bits.LeadingZeros8(x) == 0 {
b[i] = 1
}
x = bits.RotateLeft8(x, 1)
}
return b
}
func signed8(x int8) []byte {
return unsigned8(uint8(x))
}
func main() {
b := signed8(-5)
fmt.Println(b) // [1 1 1 1 1 0 1 1]
}
在这种情况下,您也可以使用 [8]byte
,但如果您有
一个正整数,并且想要修剪前导零。