目次
| Operator" >| Operator
ビット操作の構成の使用法" >ビット操作の構成の使用法
#^ 演算子 " >#^ 演算子
ホームページ バックエンド開発 Golang Golangのビット演算を詳しく解説

Golangのビット演算を詳しく解説

Sep 21, 2022 am 11:09 AM
go golang

この記事では、Golang のビット演算を深く理解し、各演算子の詳細な事例とその使用方法を紹介します。

Golangのビット演算を詳しく解説

コンピュータのメモリが高価で処理能力が限られていた古き良き時代には、情報を処理するためにハッカースタイルのビット演算を使用することが好まれていた方法でした(場合によっては、こちらです)。今日に至るまで、ビット演算の直接使用は、低レベルのシステム プログラミング、グラフィックス処理、暗号化など、多くのコンピューティング分野で不可欠な部分となっています。 [関連する推奨事項: Go ビデオ チュートリアル ]

Go プログラミング言語は、次のビット単位の演算子をサポートしています:

&   bitwise AND
 |   bitwise OR
 ^   bitwise XOR
&^   AND NOT
<<   left shift
>>   right shift
ログイン後にコピー

この記事の残りの部分では、各演算子とその使用方法について詳しく説明します。それ。

& 演算子

Go では、& 演算子は 2 つの整数オペランドに対して次の演算を実行します: ビット AND の操作。 AND 演算には次のプロパティがあります。

Given operands a, b
AND(a, b) = 1; only if a = b = 1
               else = 0
ログイン後にコピー

AND この演算子には、整数データのビットを選択的に 0 にクリアするという優れた効果があります。たとえば、& 演算子を使用して、最後の 4 つの最下位ビット (LSB) をすべて 0 にクリア (設定) できます。

func main() {
    var x uint8 = 0xAC    // x = 10101100
    x = x & 0xF0          // x = 10100000
}
ログイン後にコピー

すべてのビット演算は、省略された代入形式をサポートしています。たとえば、前の例は次のように書き換えることができます。

func main() {
    var x uint8 = 0xAC    // x = 10101100
    x &= 0xF0             // x = 10100000
}
ログイン後にコピー

もう 1 つの巧妙なトリックは、& 演算を使用して、数値が奇数か偶数かをテストできることです。その理由は、数値の最下位ビットが 1 の場合、それは奇数であるためです。数値と 1 を使用して & 演算を実行し、次に AND 演算を 1 で実行できます。結果が 1 の場合、元の数値は奇数です

import (
    "fmt"
    "math/rand"
)
func main() {
    for x := 0; x < 100; x++ {
        num := rand.Int()
        if num&1 == 1 {
            fmt.Printf("%d is odd\n", num)
        } else {
            fmt.Printf("%d is even\n", num)
        }
    }
}
ログイン後にコピー

上記の例を Playground で実行します

| 実行します整数オペランドに対するビットごとの または 演算。 または

演算子には次のプロパティがあることを思い出してください。

Given operands a, b
OR(a, b) = 1; when a = 1 or b = 1
              else = 0
ログイン後にコピー
ビットごとの または 演算子を使用して、特定の整数の個々のビットを選択的に設定できます。たとえば、次の例では、ビット単位の または

を使用して、例の番号の 3 番目、7 番目、および 8 番目のビット (下位ビットから上位ビット (MSB) まで) を 1 に設定します。

func main() {
    var a uint8 = 0
    a |= 196
    fmt.Printf("%b", a)
}

// 打印结果  11000100
            ^^   ^
ログイン後にコピー
例はゴルフ練習場で実行できます

または 演算は、ビット マスキング手法を使用して特定の整数に任意のビットを設定する場合に便利です。たとえば、前のプログラムを拡張して、変数 a

に格納されている値により多くのビットを設定できます。

func main() {
    var a uint8 = 0
    a |= 196
    a |= 3
    fmt.Printf("%b", a)
}

// 打印结果 11000111
ログイン後にコピー
サンプルは、練習フィールド

で実行できます。

前のプログラムでは、10 進数の 196 をビットごとに設定する必要があるだけでなく、下位ビットの 10 進数の 3 も設定する必要があります。続行して ( または

にさらに値を追加)、すべてのビットを設定します。

ここで、AND(a, 1) = a の場合および a = 1 の場合にのみ確認してください。 。この機能を使用して、設定ビットの値を問い合わせることができます。たとえば、上記のコード a & 196 は、これらのビットの値が a に存在するため、196 を返します。したがって、ORAND

演算を組み合わせて使用​​して、特定のビットの構成値をそれぞれ設定および読み取ることができます。 .

次のソース コード スニペットは、この操作を示しています。関数 procstr は文字列の内容を変換します。 2 つのパラメータが必要です: 1 つ目の str は変換する文字列で、2 つ目の conf

は複数の変換構成を指定するビット マスクです。

const (
    UPPER  = 1 // 大写字符串
    LOWER  = 2 // 小写字符串
    CAP    = 4 // 字符串单词首字母大写
    REV    = 8 // 反转字符串
)

func main() {
    fmt.Println(procstr("HELLO PEOPLE!", LOWER|REV|CAP))
}

func procstr(str string, conf byte) string {
    // 反转字符串
    rev := func(s string) string {
        runes := []rune(s)
        n := len(runes)
        for i := 0; i < n/2; i++ {
            runes[i], runes[n-1-i] = runes[n-1-i], runes[i]
        }
        return string(runes)
    }

    // 查询配置中的位操作
    if (conf & UPPER) != 0 {
        str = strings.ToUpper(str)
    }
    if (conf & LOWER) != 0 {
        str = strings.ToLower(str)
    }
    if (conf & CAP) != 0 {
        str = strings.Title(str)
    }
    if (conf & REV) != 0 {
        str = rev(str)
    }
    return str
}
ログイン後にコピー

プレイグラウンドでコードを実行します。

上記の procstr("HELLO PEOPLE!", LOWER|REV|CAP) メソッドは文字列を小文字に変換します。次に、文字列を反転し、最後に文字列内の単語の最初の文字を大文字にします。この機能は、conf

の 2 桁目、3 桁目、4 桁目を 14 に設定することで実現されます。次に、コードは連続する if ステートメント ブロックを使用してこれらのビット操作を取得し、対応する文字列変換を実行します。 #Go では、ビットごとの

#XOR 演算は # を使用して実行されます。急行。 XOR 演算子には次の特性があります。

Given operands a, b
XOR(a, b) = 1; only if a != b
     else = 0
ログイン後にコピー

XOR 演算 のこの特性は、バイナリ ビットの 1 つの値を別の値に変更するために使用できます。たとえば、16 進値が与えられた場合、次のコードを使用して、値の最初の 8 ビット (MSB から開始) を切り替えることができます。

func main() {
    var a uint16 = 0xCEFF
    a ^= 0xFF00 // same a = a ^ 0xFF00
}

// a = 0xCEFF   (11001110 11111111)
// a ^=0xFF00   (00110001 11111111)
ログイン後にコピー

在前面的代码片段中,与 1 进行异或的位被翻转(从 0 到 1 或从 1 到 0)。异或 运算的一个实际用途,例如,可以利用 异或运算去比较两个数字的符号是否一样。当 (a ^ b) ≥ 0 (或相反符号的 (a ^ b) < 0 )为 true 的时候,两个整数 a,b 具有相同的符号,如下面的程序所示:

func main() {
    a, b := -12, 25
    fmt.Println("a and b have same sign?", (a ^ b) >= 0)
}
ログイン後にコピー

在 Go 的 Playground运行代码。

当执行上面这个程序的时候,将会打印出:a and b have same sign? false。在 Go Playground 上修改程序里 a ,b 的符号,以便看到不同的结果。

^ 作为取反位运算符 (非)

不像其他语言 (c/c++,Java,Python,Javascript,等), Go 没有专门的一元取反位运算符。取而代之的是,XOR 运算符 ^,也可作为一元取反运算符作用于一个数字。对于给定位 x,在 Go 中 x = 1 ^ x 可以翻转该位。在以下的代码段中我们可以看到使用 ^a 获取变量 a 的取反值的操作。

func main() {
    var a byte = 0x0F
    fmt.Printf("%08b\n", a)
    fmt.Printf("%08b\n", ^a)
}

// 打印结果
00001111     // var a
11110000     // ^a
ログイン後にコピー

练习场中可以运行范例。

&^ 操作符

&^ 操作符意为 与非,是 操作符的简写形式,它们定义如下。

Given operands a, b
AND_NOT(a, b) = AND(a, NOT(b))
ログイン後にコピー

如果第二个操作数为 1 那么它则具有清除第一个操作数中的位的趣味特性。

AND_NOT(a, 1) = 0; clears a
AND_NOT(a, 0) = a;
ログイン後にコピー

接下来的代码片段使用 AND NOT 操作符,将变量值1010 1011变为 1010 0000,清除了操作数上的低四位。

func main() {
    var a byte = 0xAB
     fmt.Printf("%08b\n", a)
     a &^= 0x0F
     fmt.Printf("%08b\n", a)
}

// 打印:
10101011
10100000
ログイン後にコピー

练习场中运行范例。

<< 和 >> 操作符

与其他 C 的衍生语言类似, Go 使用 << 来表示左移运算符和右移运算符,如下所示:

Given integer operands a and n,
a << n; shifts all bits in a to the left n times
a >> n; shifts all bits in a to the right n times
ログイン後にコピー

例如,在下面的代码片段中变量 a00000011)的值将会左移位运算符分别移动三次。每次输出结果都是为了说明左移的目的。

func main() {
    var a int8 = 3
    fmt.Printf("%08b\n", a)
    fmt.Printf("%08b\n", a<<1)
    fmt.Printf("%08b\n", a<<2)
    fmt.Printf("%08b\n", a<<3)
}

// 输出的结果:
00000011
00000110
00001100
00011000
ログイン後にコピー

Playground 运行代码

注意每次移动都会将低位右侧补零。相对应,使用右移位操作符进行运算时,每个位均向右方移动,空出的高位补零,如下示例 (有符号数除外,参考下面的算术移位注释)。

func main() {
 var a uint8 = 120
 fmt.Printf("%08b\n", a)
 fmt.Printf("%08b\n", a>>1)
 fmt.Printf("%08b\n", a>>2)
}

// 打印:
01111000
00111100
00011110
ログイン後にコピー

练习场中可以运行范例。

可以利用左移和右移运算中,每次移动都表示一个数的 2 次幂这个特性,来作为某些乘法和除法运算的小技巧。例如,如下代码中,我们可以使用右移运算将 200(存储在变量 a 中)除以 2 。

func main() {
    a := 200
    fmt.Printf("%d\n", a>>1)
}

// 打印:
100
ログイン後にコピー

练习场 中可以运行范例。

或是通过左移 2 位,将一个数乘以4:

func main() {
    a := 12
    fmt.Printf("%d\n", a<<2)
}
// 打印:

48
ログイン後にコピー

练习场 中可以运行范例。

位移运算符提供了有趣的方式处理二进制值中特定位置的值。例如,下列的代码中,|<< 用于设置变量 a 的第三个 bit 位。

func main() {
    var a int8 = 8
    fmt.Printf("%08b\n", a)
    a = a | (1<<2)
    fmt.Printf("%08b\n", a)
}
// prints:
00001000
00001100
ログイン後にコピー

可以在 练习场 中运行代码示例。

或者,您可以组合位移运算符和 & 测试是否设置了第n位,如下面示例所示:

func main() {
    var a int8 = 12
    if a&(1<<2) != 0 {
        fmt.Println("take action")
    }
}

// 打印:
take action
ログイン後にコピー

练习场中运行代码。

使用  &^ 和位移运算符,我们可以取消设置一个值的某个位。例如,下面的示例将变量 a 的第三位置为 0 :

func main() {
    var a int8 = 13 
    fmt.Printf("%04b\n", a)
    a = a &^ (1 << 2)
    fmt.Printf("%04b\n", a)
}

// 打印:
1101
1001
ログイン後にコピー

练习场 中运行代码。

关于算术位移运算的笔记

当要位移的值(左操作数)是有符号值时,Go 自动应用算术位移。在右移操作期间,复制(或扩展)二进制补码符号位以填充位移的空隙。

概要

他の最新の演算子と同様に、Go はすべてのバイナリ ビット操作演算子をサポートしています。この記事では、これらの演算子を使用して実行できるさまざまなハックの例を紹介するだけです。ウェブ上には多くの記事、特に Sean Eron Anderson が書いた Bit Twiddle Hacks が見つかります。

Twitter で Vladim @vladimirvivien をフォローしてください。

Go を学習している場合は、Vladimir Vivien の Go に関する書籍 Learning Go Programming を読んでください。

この記事はもともと著者の Vladimir Vivien によって Medium で Bit Hacking with Go として公開されたものです。

英語の元のアドレス: https://dev.to/vladimirvivien/bit-hacking-with-go

プログラミング関連の知識の詳細については、次のサイトを参照してください: プログラミングビデオ! !

以上がGolangのビット演算を詳しく解説の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

Golang を使用してファイルを安全に読み書きするにはどうすればよいですか? Golang を使用してファイルを安全に読み書きするにはどうすればよいですか? Jun 06, 2024 pm 05:14 PM

Go ではファイルを安全に読み書きすることが重要です。ガイドラインには以下が含まれます。 ファイル権限の確認 遅延を使用してファイルを閉じる ファイル パスの検証 コンテキスト タイムアウトの使用 これらのガイドラインに従うことで、データのセキュリティとアプリケーションの堅牢性が確保されます。

Golang データベース接続用の接続プールを構成するにはどうすればよいですか? Golang データベース接続用の接続プールを構成するにはどうすればよいですか? Jun 06, 2024 am 11:21 AM

Go データベース接続の接続プーリングを構成するにはどうすればよいですか?データベース接続を作成するには、database/sql パッケージの DB タイプを使用します。同時接続の最大数を制御するには、MaxOpenConns を設定します。アイドル状態の接続の最大数を設定するには、ConnMaxLifetime を設定します。

golangフレームワークの長所と短所の比較 golangフレームワークの長所と短所の比較 Jun 05, 2024 pm 09:32 PM

Go フレームワークは、その高いパフォーマンスと同時実行性の利点で際立っていますが、比較的新しい、開発者エコシステムが小さい、一部の機能が欠けているなどの欠点もあります。さらに、急速な変化と学習曲線はフレームワークごとに異なる場合があります。 Gin フレームワークは、効率的なルーティング、組み込みの JSON サポート、強力なエラー処理機能により、RESTful API を構築するための一般的な選択肢です。

Golang 単体テストのアサーションに gomega を使用するにはどうすればよいですか? Golang 単体テストのアサーションに gomega を使用するにはどうすればよいですか? Jun 05, 2024 pm 10:48 PM

Golang 単体テストでアサーションに Gomega を使用する方法 Golang 単体テストでは、Gomega は、開発者がテスト結果を簡単に検証できるように、豊富なアサーション メソッドを提供する人気のある強力なアサーション ライブラリです。 Gomegagoget-agithub.com/onsi/gomega をインストールする アサーションに Gomega を使用する アサーションに Gomega を使用する一般的な例をいくつか示します。 1. 等価アサーション import "github.com/onsi/gomega" funcTest_MyFunction(t*testing.T){

Golang フレームワークでのエラー処理のベスト プラクティスは何ですか? Golang フレームワークでのエラー処理のベスト プラクティスは何ですか? Jun 05, 2024 pm 10:39 PM

ベスト プラクティス: 明確に定義されたエラー タイプ (エラー パッケージ) を使用してカスタム エラーを作成する 詳細を提供する エラーを適切にログに記録する エラーを正しく伝播し、非表示または抑制しないようにする コンテキストを追加するために必要に応じてエラーをラップする

GolangでJSONデータをデータベースに保存するにはどうすればよいですか? GolangでJSONデータをデータベースに保存するにはどうすればよいですか? Jun 06, 2024 am 11:24 AM

JSON データは、gjson ライブラリまたは json.Unmarshal 関数を使用して MySQL データベースに保存できます。 gjson ライブラリは、JSON フィールドを解析するための便利なメソッドを提供します。json.Unmarshal 関数には、JSON データをアンマーシャリングするためのターゲット型ポインターが必要です。どちらの方法でも、SQL ステートメントを準備し、データをデータベースに永続化するために挿入操作を実行する必要があります。

Golang フレームワークと Go フレームワーク: 内部アーキテクチャと外部機能の比較 Golang フレームワークと Go フレームワーク: 内部アーキテクチャと外部機能の比較 Jun 06, 2024 pm 12:37 PM

GoLang フレームワークと Go フレームワークの違いは、内部アーキテクチャと外部機能に反映されています。 GoLang フレームワークは Go 標準ライブラリに基づいてその機能を拡張していますが、Go フレームワークは特定の目的を達成するための独立したライブラリで構成されています。 GoLang フレームワークはより柔軟であり、Go フレームワークは使いやすいです。 GoLang フレームワークはパフォーマンスの点でわずかに優れており、Go フレームワークはよりスケーラブルです。ケース: gin-gonic (Go フレームワーク) は REST API の構築に使用され、Echo (GoLang フレームワーク) は Web アプリケーションの構築に使用されます。

golang フレームワークでよくあるセキュリティ問題を解決するにはどうすればよいですか? golang フレームワークでよくあるセキュリティ問題を解決するにはどうすればよいですか? Jun 05, 2024 pm 10:38 PM

Go フレームワークで一般的なセキュリティ問題に対処する方法 Web 開発で Go フレームワークが広く採用されているため、そのセキュリティを確保することが重要です。以下は、一般的なセキュリティ問題を解決するための実践的なガイドであり、サンプル コードも含まれています。 1. SQL インジェクション SQL インジェクション攻撃を防ぐには、プリペアド ステートメントまたはパラメータ化されたクエリを使用します。例: constquery="SELECT*FROMusersWHEREusername=?"stmt,err:=db.Prepare(query)iferr!=nil{//Handleerror}err=stmt.QueryR

See all articles