按位或运算的实现区别

举报
码乐 发表于 2025/08/26 07:24:07 2025/08/26
【摘要】 1 简介在 Go 里按位或是 |,|| 是逻辑或(只用于 bool)。本文都以 按位或 | 为例说明 2 按位或的过程(Go 示例)规则(逐位): 0|0=0, 0|1=1, 1|0=1, 1|1=1 package main import "fmt" func main() { a := 6 // 0110 b := 11 // 1011 r...

1 简介

在 Go 里按位或是 |,|| 是逻辑或(只用于 bool)。本文都以 按位或 | 为例说明

2 按位或的过程(Go 示例)

规则(逐位):

		0|0=0, 0|1=1, 1|0=1, 1|1=1

		package main

		import "fmt"

		func main() {
		    a := 6   // 0110
		    b := 11  // 1011
		    r := a | b
		    fmt.Printf("%d | %d = %d\n", a, b, r)
		    fmt.Printf("a: %04b\n", a)
		    fmt.Printf("b: %04b\n", b)
		    fmt.Printf("r: %04b\n", r)
		}

输出(概念上):

		6 | 11 = 15
		a: 0110
		b: 1011
		r: 1111

逐位过程:

		  0110
		| 1011
		= 1111  (十进制 15)
  • 与 Python 的同例对比

      	a = 6
      	b = 11
      	r = a | b
      	print(a, "|", b, "=", r)
      	print(f"a: {a:04b}")
      	print(f"b: {b:04b}")
      	print(f"r: {r:04b}")
    

输出相同:

		6 | 11 = 15
		a: 0110
		b: 1011
		r: 1111

结论:按位或的语义在两种语言里是一样的:逐位取“有 1 则 1”。

3 实战的位掩码 (Go)

设定标志位(典型用法:权限/状态位):

		package main

		import "fmt"

		const (
		    Read  = 1 << iota // 0001
		    Write             // 0010
		    Exec              // 0100
		)

		func main() {
		    var perm uint8 = 0
		    perm |= Read | Exec           // 置位
		    fmt.Printf("perm: %03b\n", perm) // 101

		    hasWrite := (perm & Write) != 0
		    fmt.Println("has write?", hasWrite) // false
		}


		Python 同理:

		Read, Write, Exec = 1<<0, 1<<1, 1<<2
		perm = 0
		perm |= Read | Exec
		print(f"perm: {perm:03b}")        # 101
		print("has write?", bool(perm & Write))  # False

固定位宽 vs 任意精度的直观差别

A) 超大位的或运算

Python:

  x = 3 | (1 << 100)         # OK,得到一个 101 位整数

Go:

  x := 3 | (1 << 100)        // 编译期报错:常量溢出(默认要落到 int)
  // 需要:
  //   1) 用 math/big
  //   2) 或者把常量限制在目标类型位宽内

使用 math/big:

	package main

	import (
	    "fmt"
	    "math/big"
	)

	func main() {
	    a := big.NewInt(3)
	    b := new(big.Int).Lsh(big.NewInt(1), 100) // 1<<100
	    r := new(big.Int).Or(a, b)
	    fmt.Println(r) // 大整数结果
	}

B) 负数参与位运算的语义

Python(无限二补码):

  (-1) | 0            # -1
  (-5) | 3            # 依无限前导 1 解释;结果仍是负数

如需“按 N 位宽解释”,常用屏蔽:((x | y) & ((1<<N)-1))

Go(定宽二补码):

  var a int8 = -5            // 11111011
  var b int8 = 3             // 00000011
  fmt.Printf("%08b\n", a|b)  // 11111011  => 仍是 -5(在 int8 里)

两者数值可能一致,但解释方式不同:Python 是“无限位”,Go 是“定 N 位”。

4 按位运算的不同

  • 按位与的不同

      特性  			Go  											Python
      整数类型    固定宽度(int8, int16, int32, int64, uint 等),默认 int 依赖机器字长(32/64 位)。 int 是任意精度整数(bigint),没有固定字长限制。
      补码表示    所有有符号整数采用 补码表示,位数固定,因此高位会被截断或填充。    Python 的 int 在内部用一个符号位 + 动态数组表示(类 bigint),逻辑上可以看作“无限补码”,不会溢出。
      按位运算结果  结果会限制在类型宽度范围内(例如 int32 会截断高于 32 位的部分)。  结果可以比原数的二进制位长大,Python 会自动扩展位数。
      性能  直接映射到底层 CPU 指令,运行非常快。   Python 需要在任意精度大整数上执行逐“字块”运算,相对慢。
      应用场景    常用于底层开发、位掩码、硬件寄存器操作。    常用于数学计算或大整数算法(例如加密算法中的掩码)。
    
  • 按位或 |的不同

关键差异:算法实现与数值模型

		维度				Go													Python
		整数模型			固定宽度(int8/int16/int32/int64/uint*,int 依平台 32/64 位)。有符号整数是二补码。	int 是任意精度大整数(bigint),位数按需增长。
		按位或实现			基本映射为 CPU 的单条/少量指令,在一个机器字上做 OR(对大于字宽的类型由编译器分解为多字操作,但内置整型通常一个字)。	在 C 层面的 大整数实现:把整数拆成“字数组”,逐“字”做 OR,必要时扩容。
		
		溢出/截断	结果被限制在类型位宽内。超出位宽的高位被截断(对 `	` 本身不产生进位,但参与表达式的其它操作/常量转换可能报溢出或截断)。
		
		负数参与位运算	以固定宽度二补码解释:例如 int8(-5) 的位模式是 11111011。	采用“无限位二补码语义”:负数视为无限前导 1 的扩展。
		
		类型约束	   不同整型不能直接混用,需显式转换;`	不能用于bool`。
		
		大整数	需用 math/big:big.Int 的 Or(x, y) 方法。	内建 int 就是大整数。
		
		性能	    原生整数位运算非常快、接近硬件。	大整数按“字数组”逐块运算,开销更大;小整数仍很快,但不及原生编译型直达指令。

5 布尔与集合等的“|”差异

Go:

	按位或:  | 只用于整数位运算;布尔用 ||(逻辑或),且不能把 bool 当整数位运算。

Python:| 可用于

  bool:True | False 得到 True(布尔是 int 子类);True | 4 == 5

  set:集合并集;{1,2}|{2,3} == {1,2,3}

  dict(3.9+):字典并集(键冲突后者覆盖)

这体现了 操作符重载 与 强类型/无重载 的语言设计差异。

  • 运算符优先级与类型转换

优先级:两边基本一致——移位 << >> 高于按位与 &,高于按位异或 ^,高于按位或 |,逻辑或 ||/or 更低。
例:1 | 2 << 1 在两语言里都是 1 | 4 = 5。

类型转换(Go):不同位宽/有无符号不能直接“|”,需显式转换,否则编译错误;Python 不区分这些整型。

6 小结

语义层面:按位或在 Go 和 Python 都是“逐位有 1 则 1”。

差异主要在数值模型与实现:Go 的定宽二补码+接近硬件 → 快且可控;Python 的任意精度 → 更灵活但实现为“多字数组”算法。

处理超大数/密码学等:Python 直接用内建 int;Go 请使用 math/big((*Int).Or)。

处理固定位协议/寄存器:Go 的定宽类型(uint8/16/32/64)+ 位掩码最稳;

Python 场景下记得按位宽 & ((1<<N)-1) 进行屏蔽以模拟硬件位宽。

    Go 的按位或是 |,逻辑或是 ||;

    Python 的逻辑或是 or,|| 不合法。
【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。