本文介绍了一些运算符“|"、“^"、“&"、“&^"之间的区别.高朗的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

最近阅读了 golang 规范,遇到了一些有趣的操作符:

Recently I read golang specification and faced with some interesting operators:

&    bitwise AND            integers
|    bitwise OR             integers
^    bitwise XOR            integers
&^   bit clear (AND NOT)    integers

我试过玩它,但我唯一理解的是|"添加整数和+"运算符还可以处理浮点数、字符串等.

I've tried to play with it, but the only one I have understood is that "|" add integers and "+" operator additionally work with floats, strings etc.

它们在实践中的用途是什么?谁能解释一下上面这4个操作符?

What they are used for in practice? Could anyone give some explanation about these 4 operators above?

推荐答案

当您必须处理字节或位级数据时,位运算符就会发挥作用.

Bitwise operators come into play when you have to work with byte- or bit-level data.

这里我列出了一些使用位操作和代码示例的示例(无特定顺序):

Here I list a handful of examples using bit operations with code samples (in no particular order):

1.它们很常见,并且是密码学哈希函数中许多算法的一部分(例如MD5).

1. They are common and part of many algorithms in cryptography and hash functions (e.g. MD5).

2.如果您想节省"空间并且将多个bool"变量打包成一个int,它们也经常使用例如,您为每个 bool 变量分配一个位.您必须使用按位运算符才能单独更改/读取位.

2. They are also often used if you want to "save" space and you pack multiple "bool" variables into one int for example, you assign a bit to each bool variable. You have to use bitwise operators to be able to individually change/read the bits.

例如将 8 bits/bools 打包成一个 int:

For example packing 8 bits/bools into one int:

flags := 0x00  // All flags are 0
flags |= 0x02  // Turn the 2nd bit to 1 (leaving rest unchanged)
flags |= 0xff  // Turn 8 bits (0..7) to 1
flags &= 0xfe  // Set the lowest bit to 0 (leaving rest unchanged)

istrue := flags&0x04 != 0 // Test if 3rd bit is 1

3. 另一个领域是压缩数据,您希望在其中充分利用字节并使用其所有位来存储/检索一些信息(比特是计算和数字通信中信息的基本单位).

3. Another area is compressing data where you want to get the most out of a byte and use all its bits to store/retreive some info (a bit is the basic unit of information in computing and digital communications).

4. 与压缩类似但不完全相同:比特流.它还用于通过不发送完整字节而是发送具有任意位长的字段来节省数据流中的空间.

4. Similar to compression but not quite the same: bitstreams. It is also used to save space in a data stream by not sending complete bytes but rather fields having arbitrary bit-length.

我编写并发布了一个高度优化的位级读写器包,在这里开源:github.com/icza/bitio.您将在其源代码中看到各种位操作的广泛使用.

I've written and published a highly optimized bit-level Reader and Writer package, open sourced here: github.com/icza/bitio. You will see extensive usage of all kinds of bit operations in its sources.

5. 另一个实际用途:测试(整数)数的某些属性.了解整数的二进制表示(二的补码),在其二进制表示中,数字具有某些特征.例如,如果最低位为 0,则整数(以 2 的补码形式)是 偶数(可以被 2 整除):

5. Another practical usage: testing certain properties of an (integer) number. Knowing the binary representation of integer numbers (Two's complement) there are certain characteristics of numbers in their binary representation. For example an integer number (in 2's complement) is even (can be divided by 2) if the lowest bit is 0:

func isEven(i int) bool {
    return i&0x01 == 0
}

通过测试一个整数的位,您还可以判断它是否是 2 的幂.例如,如果一个正数只包含一个 1 位,那么它就是 2 的幂(例如 2 = 0x02 = 00000010b, 16 = 0x10 = 00010000 但例如 17 = 0x11 = 00010001 不是 2 的幂.

By testing the bits of an integer you can also tell if it's a power of 2. For example if a positive number only contains one 1 bit, then it is a power of 2 (e.g. 2 = 0x02 = 00000010b, 16 = 0x10 = 00010000 but for example 17 = 0x11 = 00010001 not power of 2).

6. 许多编码/解码过程也使用位操作.最简单的是 UTF-8 编码,它使用可变长度编码来表示 unicode 代码点(rune 在 Go 中)作为字节序列.
可变长度编码的一个简单变体可能是使用字节的最高位(如果是 0 索引,则为第 8 位或第 7 位)来表示是否需要更多字节来解码一个数字,而其余 7 位始终是有用的""数据.您可以测试最高位并分离"7 个有用的位,如下所示:

6. Many encoding/decoding procedures also use bit operations. The most trivial is the UTF-8 encoding which uses a variable-length encoding for representing unicode code points (rune in Go) as byte sequences.
A simple variation of a variable-length encoding could be to use the highest bit of a byte (8th or 7th if 0-indexed) to signal if more bytes are required to decode a number, and the remaining 7 bits are always the "useful" data. You can test the highest bit and "separate" the 7 useful bits like this:

b := readOneByte()
usefulBits := b & 0x7f
hasMoreBytes := b & 0x80 != 0

使用这种变长编码的好处是,即使你在 Go 中使用 uint64 类型,它在内存中占 8 个字节,小数字仍然可以用更少的字节表示(数字在范围 0..127 只需要 1 个字节!).如果您要存储或传输的样本有许多小值,仅此一项就可以将数据压缩到 1/8 = 12.5 %.不利的一面是大数字(即使在最高字节中也有位)将使用超过 8 个字节.是否值得取决于样本的启发式.

The profit of using such a variable-length encoding is that even if you use uint64 type in Go which is 8 bytes in memory, small numbers can still be represented using less bytes (numbers in the range 0..127 only require 1 byte!). If the samples you want to store or transfer have many small values, this alone can compress the data to 1/8th = 12.5 %. The down side is that big numbers (which have bits even in the highest byte) will use more than 8 bytes. Whether it's worth it depends on the heuristic of the samples.

X. 这个列表还在继续......

如果不知道/使用 Go(以及许多其他编程语言)中的按位运算符,你能活下去吗?答案是肯定的.但是,如果您了解它们,有时它们可​​以让您的生活更轻松,您的程序更高效.

Can you live without knowing/using bitwise operators in Go (and in many other programming languages)? The answer is Yes. But if you know them, sometimes they can make your life easier and your programs more efficient.

如果您想了解有关该主题的更多信息,请阅读维基百科文章:Bitwise operation 并在谷歌上搜索BitwiseOperators Tutorial》,有很多好文章.

If you want to learn more on the topic, read the Wikipedia article: Bitwise operation and google the term "Bitwise Operators Tutorial", there are many good articles.

这篇关于一些运算符“|"、“^"、“&"、“&^"之间的区别.高朗的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-16 16:46
查看更多