信奥崔老思:逻辑运算

93 阅读4分钟

4.3 逻辑运算 (Logical Operations)

图片

1. 概念介绍

逻辑运算用于组合或修改布尔值(true/false),通常与关系运算结合使用,以构建更复杂的条件判断。

  • 逻辑与 (&&) : AND。当且仅当两个操作数都为 true 时,结果才为 true
  • 逻辑或 (||) : OR。只要两个操作数中至少有一个为 true,结果就为 true
  • 逻辑非 (!) : NOT。反转操作数的布尔值。!true 结果为 false!false 结果为 true

2. 算法步骤

  1. 逻辑非 (!) : 计算操作数的布尔值,然后取反。
  2. 逻辑与 (&&) : a. 计算左操作数。 b. 如果左操作数为 false,则不再计算右操作数,直接返回 false短路求值)。 c. 如果左操作数为 true,则计算右操作数,并返回其结果。
  3. 逻辑或 (||) : a. 计算左操作数。 b. 如果左操作数为 true,则不再计算右操作数,直接返回 true短路求值)。 c. 如果左操作数为 false,则计算右操作数,并返回其结果。

3. 算法可视化SVG图示

下图用逻辑门的样式展示了三种逻辑运算。

图片

4. 核心特性

  • 短路求值 (Short-circuit Evaluation) : 这是逻辑运算最重要的特性。
    • A && B:如果 A 为假,则 B 表达式根本不会被执行。
    • A || B:如果 A 为真,则 B 表达式根本不会被执行。 这个特性可以用于避免错误(如 if (ptr != nullptr && ptr->value > 0))和进行性能优化。
  • 优先级! (非) > && (与) > || (或)。
  • 操作数: 可以是任何能转换为布尔值的表达式(在C++中,非零值为 true,零值为 false)。

5. C++代码基础实现

#include <iostream>

int main() {
    bool is_student = true;
    int age = 15;
    bool has_ticket = false;

    std::cout << std::boolalpha;

    // 逻辑与 &&
    // 是学生并且年龄小于18岁吗?
    if (is_student && age < 18) {
        std::cout << "Is a minor student: true" << std::endl;
    }

    // 逻辑或 ||
    // 是学生或者有票吗?
    if (is_student || has_ticket) {
        std::cout << "Can enter (student or has ticket): true" << std::endl;
    }

    // 逻辑非 !
    // 没有票吗?
    if (!has_ticket) {
        std::cout << "Does not have a ticket: true" << std::endl;
    }

    return0;
}

6. 优化策略

  • 利用短路特性:
    • 在 && 链中,将最可能为 false 的条件或计算成本最低的条件放在最前面。
    • 在 || 链中,将最可能为 true 的条件或计算成本最低的条件放在最前面。
  • 化简逻辑: 使用德摩根定律等布尔代数规则来化简复杂的逻辑表达式。例如 !(A || B) 等价于 !A && !B

7. 优缺点

  • 优点: 能够构建任意复杂的判断逻辑,是程序控制流的粘合剂。短路特性可以提升效率和代码安全性。
  • 缺点: 复杂的嵌套逻辑表达式会降低代码的可读性。

8. 应用场景

  • 数据校验: 检查输入数据是否同时满足多个条件(例如,年龄在18-60之间 age >= 18 && age <= 60)。
  • 状态判断: 在游戏中判断游戏结束条件(例如,生命值为0或时间耗尽 health <= 0 || time_left <= 0)。
  • 权限控制: 判断用户是否具有执行某项操作的权限。
  • 算法分支: 在算法中根据多个条件的组合来选择不同的执行路径。

9. 扩展

  • 位逻辑运算符 (&|^~) : 这些是位运算符,对整数的每个二进制位进行逻辑运算,与逻辑运算符 &&||! 不同。不要混淆。
  • 布尔代数: 逻辑运算是布尔代数的基础,理解布尔代数有助于简化和优化逻辑表达式。

10. 课后配套练习及答案

练习1: 区间判断输入一个整数,判断它是否在区间 [10, 20] 内(包含10和20)。

// 答案
#include <iostream>
int main() {
    int n;
    std::cin >> n;
    if (n >= 10 && n <= 20) {
        std::cout << "In range" << std::endl;
    } else {
        std::cout << "Out of range" << std::endl;
    }
    return 0;
}

练习2: 判断元音字母输入一个字符,判断它是否是元音字母(a, e, i, o, u,不区分大小写)。

// 答案
#include <iostream>
#include <cctype> // for tolower
int main() {
    char c;
    std::cin >> c;
    c = tolower(c);
    if (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u') {
        std::cout << "Vowel" << std::endl;
    } else {
        std::cout << "Consonant" << std::endl;
    }
    return 0;
}

练习3: 判断点是否在矩形内输入一个点的坐标(x, y)和一个矩形的左上角坐标(x1, y1)和右下角坐标(x2, y2),判断该点是否在矩形内(含边界)。

// 答案
#include <iostream>
int main() {
    int x, y, x1, y1, x2, y2;
    std::cin >> x >> y >> x1 >> y1 >> x2 >> y2;
    if (x >= x1 && x <= x2 && y >= y1 && y <= y2) {
        std::cout << "Inside" << std::endl;
    } else {
        std::cout << "Outside" << std::endl;
    }
    return 0;
}

练习4: 登录验证模拟登录,只有当用户名是 "admin" 并且密码是 "123456" 时,才输出 "Login success"。

// 答案
#include <iostream>
#include <string>
int main() {
    std::string username, password;
    std::cin >> username >> password;
    if (username == "admin" && password == "123456") {
        std::cout << "Login success" << std::endl;
    } else {
        std::cout << "Login failed" << std::endl;
    }
    return 0;
}

练习5: 判断三角形输入三角形的三条边长 a, b, c,判断它们是否能构成一个三角形(任意两边之和大于第三边)。

// 答案
#include <iostream>
int main() {
    int a, b, c;
    std::cin >> a >> b >> c;
    if (a > 0 && b > 0 && c > 0 && (a + b > c) && (a + c > b) && (b + c > a)) {
        std::cout << "Valid triangle" << std::endl;
    } else {
        std::cout << "Invalid triangle" << std::endl;
    }
    return 0;
}

11. 相关网络资源推荐

  • C++ Logical Operators - cppreference.com
  • Short-circuit Evaluation - Wikipedia