404 Not Found

404 Not Found


nginx

Rustの演算子と式:算術演算からビット演算までを網羅したガイド

Rustでは、ifmatchを含め、ほぼすべてが式です。

式(値を返すもの)と文(値を返さないもの)の違いを理解することは、簡潔なRustコードを書くための鍵となります。


1. 学習内容


2. レジ係の物語

(1) もどかしさ:割引の計算をするたびに間違いをしてしまう

トムは衣料品店の店長で、毎日さまざまな割引の計算をしなければなりません:

「正しい順序で自動的に計算を行ってくれる電卓があれば、最高なのに……」

(2) Rustの式体系

RUST
fn main() {
    let price: f64 = 299.0;      // A piece of clothing 299 yuan
    let quantity: i32 = 3;        // Bought 3 items
    let is_member: bool = true;   // Is a member

    // Calculate all discounts with a single expression
    let total = (price * quantity as f64)           // Original Price
        * if quantity >= 3 { 0.7 } else { 0.9 }    // Volume Discount
        * if is_member { 0.95 } else { 1.0 };      // Member Discounts

    println!("Original Price: {:.2} yuan", price * quantity as f64);
    println!("Price after discount: {:.2} yuan", total);
    println!("Save: {:.2} yuan", price * quantity as f64 - total);
}

Rustでは、ifはそれ自体が式であり、直接値を返すことができます。これにより、割引の計算を単一の式の連鎖として表現することができ、エラーのリスクを排除できます。


3. 演算子のリスト

100%
graph TB
    A[Rust Operators] --> B[Arithmetic: + - * / %]
    A --> C[Comparison: == != < > <= >=]
    A --> D[Logic: && || !]
    A --> E[Bitwise Operations: & | ^ << >>]
    A --> F[Assignment: = += -= *= /=]

(1) 算術演算子

演算子 説明
+ a + b 追加
- a - b 引き算
* a * b 乗算
/ a / b 除算(整数切り捨て)
% a % b 残りの部分
- -a 負の値(単項)

整数除算では切り捨てが行われます5 / 2 = 2(2.5ではありません)。浮動小数点数の結果を得るには、浮動小数点型を使用する必要があります:5.0 / 2.0 = 2.5

(2) 比較演算子

すべての比較演算子は、bool 型の値(true または false)を返します。

RUST
let a = 10;
let b = 20;
println!("{}", a == b);  // false
println!("{}", a != b);  // true
println!("{}", a < b);   // true

(3) 論理演算子

演算子 名称 説明
&& 論理 AND a && b 両方が真の場合にのみ真(短絡評価)
` ` 論理OR
! 論理NOT !a 反転

短絡評価&&—左辺が偽の場合、右辺は評価されない;||—左辺が真の場合、右辺は評価されない。これは「アクセス前のチェック」パターンで使用できる。

(4) ビット演算子

演算子 名称 説明
& ビット単位のAND a & b 対応するすべてのビットが1の場合にのみ1となる
` ` ビット単位のOR `a
^ ビット単位のXOR a ^ b 対応するビットが異なる場合にのみ1となる
<< 左シフト a << n nビット左シフト(2^n倍に相当)
>> 右シフト a >> n nビット右シフト(2^nで割ることに相当)

4. 式と文

(1) 主な相違点

概念 定義
戻り値があるか 5 + 38 を返し、if true { 1 } else { 0 }1 を返す
ステートメント 戻り値なし let x = 5; 戻り値なし、fn foo() {} 戻り値なし

Rustでは、セミコロンによって、それが式なのか文なのかが決まります:

RUST
fn main() {
    let y = {
        let x = 3;
        x + 1       // No semicolons -- This is an expression, Returns 4
    };               // End of semicolon let Statement

    println!("y the value: {}", y);  // 4
}

(2) ブロック式

{} ブロック内のコードブロックは式とすることができます。最後の行がセミコロンで終わっていない場合、そのブロックは値を返します:

RUST
let result = {
    let a = 2;
    let b = 3;
    a * b           // No semicolons, This expression returns 6
};

5. 演算子の例

(1) ▶ サンプル:算術演算と型(難易度 ⭐)

RUST
// ============================================
// Demonstration of Arithmetic Operators——Note: Truncation in integer division
// ============================================

fn main() {
    let a = 10;
    let b = 3;

    println!("Addition: {} + {} = {}", a, b, a + b);
    println!("Subtraction: {} - {} = {}", a, b, a - b);
    println!("Multiplication: {} * {} = {}", a, b, a * b);
    println!("Integer Division: {} / {} = {} (Truncation)", a, b, a / b);
    println!("Floating-Point Division: {} / {} = {:.2}", a as f64, b as f64, a as f64 / b as f64);
    println!("Modulo: {} % {} = {}", a, b, a % b);
}

出力:

TEXT
Addition: 10 + 3 = 13
Subtraction: 10 - 3 = 7
Multiplication: 10 * 3 = 30
Integer Division: 10 / 3 = 3 (Truncation)
Floating-Point Division: 10 / 3 = 3.33
Modulo: 10 % 3 = 1

as キーワードは型変換に使用されます。a as f64 浮動小数点数の結果を得るには、除算を行う前に整数を浮動小数点数に変換してください。


(2) ▶ サンプル:論理演算の短絡評価(難易度:⭐⭐)

RUST
// ============================================
// Short-Circuit Evaluation of Logical Operators
// ============================================

fn main() {
    let age = 17;
    let has_id = true;

    // && Short Circuit: If the left is false, the right side is not executed
    let can_buy = age >= 18 && has_id;
    println!("Available for purchase (&&): {}", can_buy);  // false (Since the left side is already false)

    // || Short Circuit: If the left is true, the right side is not executed
    let is_ok = true || (expensive_check());
    println!("(|| Short Circuit, The right side will not be executed): {}", is_ok);
}

fn expensive_check() -> bool {
    println!("This function will not be executed!");
    true
}

出力:

TEXT
Available for purchase (&&): false
(|| Short Circuit, The right side will not be executed): true

ショートサーキット評価は、パフォーマンスを最適化するための重要な手法です。これは、不要な計算を避けるために、コストの低いチェックを左側に、コストの高いチェックを右側に配置するものです。


(3) ▶ サンプル:式ブロックの戻り値 (難易度 ⭐⭐)

RUST
// ============================================
// Using Expression Blocks to Implement Concise Assignments with Complex Conditions
// ============================================

fn main() {
    let score = 85;

    let grade = {
        if score >= 90 {
            "A"
        } else if score >= 80 {
            "B"
        } else if score >= 70 {
            "C"
        } else if score >= 60 {
            "D"
        } else {
            "F"
        }
    };  // Note: The entire if-else chain is an expression, End with a semicolon let Statement

    println!("Score: {}, Level: {}", score, grade);

    // Alternatives to Ternary Operations: Use if Expression
    let is_pass = if score >= 60 { "passed" } else { "failed" };
    println!("Result: {}", is_pass);
}

出力:

TEXT
Score: 85, Level: B
Result: passed

Rustには三項演算子(condition ? a : b)はありませんが、ifはそれ自体が式であり、より読みやすい形で同じ結果を得ることができます。


(4) ▶ サンプル:ビット演算の実践――アクセス権フラグと色の混合(難易度 ⭐⭐)

RUST
// ============================================
// Bitwise Operations in Practice:File Permissions and RGB Color Manipulation
// ============================================

fn main() {
    let read_perm: u8    = 0b100;   // 4
    let write_perm: u8   = 0b010;   // 2
    let exec_perm: u8    = 0b001;   // 1

    let user_perm = read_perm | write_perm;
    println!("User Permissions: {:03b} (Read+Write)", user_perm);

    let full_perm = read_perm | write_perm | exec_perm;
    println!("Full Permissions: {:03b} (Read+Write+Execute)", full_perm);

    let can_read = (user_perm & read_perm) != 0;
    let can_exec = (user_perm & exec_perm) != 0;
    println!("User-readable: {}, Executable: {}", can_read, can_exec);

    let no_write = user_perm & !write_perm;
    println!("Remove Write Permissions: {:03b}", no_write);

    let toggled = user_perm ^ exec_perm;
    println!("Toggle the execution bit: {:03b}", toggled);

    let red: u32   = 0xFF0000;
    let green: u32 = 0x00FF00;
    let blue: u32  = 0x0000FF;
    let yellow = red | green;
    let white = red | green | blue;
    println!("\nRed: {:06X}", red);
    println!("Yellow (Red|Green): {:06X}", yellow);
    println!("White (Red|Green|Blue): {:06X}", white);

    let pixel: u32 = 0xFF8040;
    let r = (pixel >> 16) & 0xFF;
    let g = (pixel >> 8)  & 0xFF;
    let b = pixel & 0xFF;
    println!("\nPixel #FF8040 → R={}, G={}, B={}", r, g, b);

    let shift_val: u8 = 1;
    println!("\n1 << 0 = {}", shift_val << 0);
    println!("1 << 1 = {}", shift_val << 1);
    println!("1 << 2 = {}", shift_val << 2);
    println!("1 << 3 = {}", shift_val << 3);
}

出力:

TEXT
User Permissions: 110 (Read+Write)
Full Permissions: 111 (Read+Write+Execute)
User-readable: true, Executable: false
Remove Write Permissions: 100
Toggle the execution bit: 111

Red: FF0000
Yellow (Red|Green): FFFF00
White (Red|Green|Blue): FFFFFF

Pixel #FF8040 → R=255, G=128, B=64

1 << 0 = 1
1 << 1 = 2
1 << 2 = 4
1 << 3 = 8

ビット演算はシステムプログラミングにおいて極めて一般的です。権限管理では、|で結合、&でチェック、& !で削除を行い、色処理では、|でブレンド、>>&でチャンネルを抽出します。<<は、2の累乗による乗算に相当します。


(5) ▶ サンプル:演算子の優先順位と複合式(難易度 ⭐⭐⭐)

RUST
// ============================================
// Operator Precedence in Practice + Compound Assignment Operator
// ============================================

fn main() {
    println!("=== Operator Precedence ===");
    let a = 2 + 3 * 4;
    println!("2 + 3 * 4 = {} (Multiply First, Then Add)", a);

    let b = (2 + 3) * 4;
    println!("(2 + 3) * 4 = {} (Parentheses Take Precedence)", b);

    let c = 10 - 6 / 2;
    println!("10 - 6 / 2 = {} (Multiply First, Then Subtract)", c);

    let d = true && false || true;
    println!("true && false || true = {} (&& Take precedence over ||)", d);

    let e = true || false && false;
    println!("true || false && false = {} (&& Take precedence over ||)", e);

    println!("\n=== Compound Assignment Operator ===");
    let mut score: i32 = 100;
    score += 20;
    println!("score += 20 → {}", score);
    score -= 30;
    println!("score -= 30 → {}", score);
    score *= 2;
    println!("score *= 2 → {}", score);
    score /= 7;
    println!("score /= 7 → {}", score);
    score %= 3;
    println!("score %= 3 → {}", score);

    println!("\n=== Chain Comparison(Using logical operators)===");
    let x = 50;
    let in_range = x >= 0 && x <= 100;
    let out_range = x < 0 || x > 100;
    println!("x={}, in [0,100]: {}, Out of range: {}", x, in_range, out_range);

    let charlie_score = 75;
    let bob_score = 88;
    let both_passed = charlie_score >= 60 && bob_score >= 60;
    let any_excellent = charlie_score >= 90 || bob_score >= 90;
    println!("Both passed: {}, Someone excellent: {}", both_passed, any_excellent);
}

出力:

TEXT
=== Operator Precedence ===
2 + 3 * 4 = 14 (Multiply First, Then Add)
(2 + 3) * 4 = 20 (Parentheses Take Precedence)
10 - 6 / 2 = 7 (Multiply First, Then Subtract)
true && false || true = true (&& Take precedence over ||)
true || false && false = true (&& Take precedence over ||)

=== Compound Assignment Operator ===
score += 20 → 120
score -= 30 → 90
score *= 2 → 180
score /= 7 → 25
score %= 3 → 1

=== Chain Comparison(Using logical operators)===
x=50, in [0,100]: true, Out of range: false
Both passed: true, Someone excellent: false

演算子の優先順位(高い順):* / %+ - → 比較演算子 → &&||。迷った場合は括弧を使用してください。「簡潔さ」よりもコードの可読性を優先してください。


❓ よくある質問

Q Rustで5 / 2はどのような値になりますか?
A 2になります(切り捨て整数除算)。
Q Rustには++や--演算子はありますか?
A いいえ。
Q && と & の違いは何ですか?
A && は論理 AND(短絡評価)であり、& はビット単位の AND(非短絡評価)です。
Q 式と文の違いはどう見分ければいいですか?
A 末尾にセミコロンがあるかどうかを確認してください。
Q as を使用した型変換における注意点は何ですか?
A as は、エラーを報告せずにデータを黙って切り捨てます。

📖 まとめ


📝 練習問題

  1. 難易度 ⭐as 変換を使用して、i32 型の 5 および 2f64 に変換し、5 / 2 = 2.5 を出力するプログラムを作成してください。
  2. 難易度 ⭐⭐:変数 x = 5 を定義し、式ブロック { x + 1 } を使用して y に値を代入し、式ブロックの外側でも x にアクセスできるかどうかを判断してください。
  3. 難易度 ⭐⭐⭐: ビット演算子を使用して関数 fn is_even(n: i32) -> bool を実装してください。この際、パリティを判定するには & のビット演算(% ではない)を使用する必要があります。
Web-Tutorial.com

Web-Tutorial 技術チーム

複数の開発者によって共同維持されているプログラミングチュートリアルプラットフォーム。各チュートリアルは専門分野の開発者が執筆・レビューしています。正確で信頼性の高いコンテンツを目指しています — 問題を見つけた場合はお知らせください。

100%