为了账号安全,请及时绑定邮箱和手机立即绑定

二进制补码和 fmt.Printf

二进制补码和 fmt.Printf

Go
慕姐8265434 2022-01-17 10:32:06
所以计算机使用二进制补码在内部表示有符号整数。即,-5 表示为 ^5 + 1 = "1111 1011"。但是,尝试打印二进制表示,例如以下代码:var i int8 = -5fmt.Printf("%b", i)输出-101。不完全是我所期望的。格式是不同的还是根本不使用二进制补码?有趣的是,转换为 unsigned int 会产生“正确”的位模式:var u uint8 = uint(i)fmt.Printf("%b", u)输出是11111011- 正好是 的 2s 补码-5。所以在我看来,这个值在内部实际上是使用二进制补码,但格式是打印无符号5并在前面加上-.有人可以澄清一下吗?
查看完整描述

3 回答

?
慕娘9325324

TA贡献1783条经验 获得超4个赞

我相信答案在于fmt模块如何格式化二进制数,而不是内部格式。


如果您看一下fmt.integer,该函数首先执行的操作之一是将带负号的整数转换为正整数:


   165      negative := signedness == signed && a < 0

   166      if negative {

   167          a = -a

   168      }

然后在此处-输出的字符串前面附加逻辑。


IOW-101确实以二进制形式-附加。5


注意:在print.gofmt.integer中调用,它本身在同一个函数中调用。pp.fmtInt64pp.printArg


查看完整回答
反对 回复 2022-01-17
?
qq_笑_17

TA贡献1818条经验 获得超7个赞

这是一种不使用的方法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,但如果您有一个正整数并且想要修剪前导零,则上述方法会更好。


https://golang.org/pkg/math/bits#RotateLeft


查看完整回答
反对 回复 2022-01-17
?
犯罪嫌疑人X

TA贡献2080条经验 获得超4个赞

必须使用不安全指针才能正确表示二进制格式的负数。


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


查看完整回答
反对 回复 2022-01-17
  • 3 回答
  • 0 关注
  • 132 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号