{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "ea6d1405",
   "metadata": {},
   "source": [
    "逻辑运算运用\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "327e3bcb",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "可以进入\n"
     ]
    }
   ],
   "source": [
    "#程序判断就是逻辑运算\n",
    "\n",
    "age = 20\n",
    "\n",
    "has_id = True\n",
    "\n",
    "#pnq:年龄满足且有证件才能进入\n",
    "if age >= 18 and has_id:\n",
    "    print('可以进入')\n",
    "\n",
    "else:\n",
    "\n",
    "    print('不可以进入')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2440e9ac",
   "metadata": {},
   "source": [
    "德摩根定律在代码中的应用1\n",
    "\n",
    "-(pnq)=-pU-q"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "c0bf88c0",
   "metadata": {},
   "outputs": [],
   "source": [
    "#方法一:\n",
    "\n",
    "if not (age >= 18 and has_id):\n",
    "    print('被拒绝')\n",
    "\n",
    "#方法二:\n",
    "\n",
    "if age < 18 or not has_id:\n",
    "\n",
    "    print('被拒绝')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "5f278472",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Numpy版本: 1.26.4\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "\n",
    "print('Numpy版本:',np.__version__)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "5744f7e1",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "向量 v= [1 2 3]\n",
      "fshape (3,)\n",
      "维度ndim= 1\n"
     ]
    }
   ],
   "source": [
    "#一继敬组（向量）\n",
    "v = np. array([1,2,3])\n",
    "print(\"向量 v=\",v)\n",
    "print(\"fshape\",v.shape)\n",
    "print(\"维度ndim=\", v.ndim)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "7eaeae37",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "矩阵A=\n",
      "[[1 2]\n",
      " [3 4]]\n",
      "形状= (2, 2)\n"
     ]
    }
   ],
   "source": [
    "#二维数组（矩阵）\n",
    "A = np.array([[1,2],[3,4]])\n",
    "print('矩阵A=')\n",
    "print(A)\n",
    "print(\"形状=\",A.shape)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e4534978",
   "metadata": {},
   "source": [
    "向量运算\n",
    "向量加法、点积、范数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "ffc5d4fe",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "v1 + v2 = [5 7 9]\n",
      "v1 * 2 = [2 4 6]\n",
      "v1 · v2 = 32\n",
      "v1 · v2 = 32\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "\n",
    "# ---------- 1. 向量基本运算 ----------\n",
    "v1 = np.array([1, 2, 3])\n",
    "v2 = np.array([4, 5, 6])\n",
    "\n",
    "print('v1 + v2 =', v1 + v2)              # 向量加法（逐元素相加）\n",
    "print('v1 * 2 =', v1 * 2)                # 标量乘法\n",
    "print('v1 · v2 =', np.dot(v1, v2))       # 点积（内积）\n",
    "print('v1 · v2 =', (v1 * v2).sum())      # 点积的另一种写法（逐元素相乘再求和）\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "56acfd8d",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "|v1| = 3.7416573867739413\n"
     ]
    }
   ],
   "source": [
    "# ---------- 2. 范数（向量的长度） ----------\n",
    "norm_v1 = np.linalg.norm(v1)\n",
    "print('|v1| =', norm_v1)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "74d1c914",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "夹角 = 12.9 度\n"
     ]
    }
   ],
   "source": [
    "# ---------- 3. 夹角计算 ----------\n",
    "cos_theta = np.dot(v1, v2) / (np.linalg.norm(v1) * np.linalg.norm(v2))\n",
    "angle = np.degrees(np.arccos(cos_theta))\n",
    "print(f'夹角 = {angle:.1f} 度')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "0ebc8894",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "a · b = 0 --> 垂直！\n"
     ]
    }
   ],
   "source": [
    "# ---------- 4. 垂直判断 ----------\n",
    "a = np.array([1, 0])\n",
    "b = np.array([0, 1])\n",
    "print('a · b =', np.dot(a, b), '--> 垂直！')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "956cddd2",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "单位向量 = [0.6 0.8] , 长度 = 1.0\n"
     ]
    }
   ],
   "source": [
    "# ---------- 5. 单位向量 ----------\n",
    "v = np.array([3, 4])\n",
    "unit_v = v / np.linalg.norm(v)\n",
    "print('单位向量 =', unit_v, ', 长度 =', np.linalg.norm(unit_v))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a968e0d8",
   "metadata": {},
   "source": [
    "矩阵运算\n",
    "乘法 矩阵变换的几何意义"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "e2df4e70",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "A @ B =\n",
      "[[19 22]\n",
      " [43 50]]\n",
      "A*B =\n",
      "[[ 5 12]\n",
      " [21 32]]\n"
     ]
    }
   ],
   "source": [
    "# ---------- 1. 矩阵乘法 vs 逐元素乘法 ----------\n",
    "A = np.array([[1, 2], [3, 4]])          # 定义 2x2 矩阵 A\n",
    "B = np.array([[5, 6], [7, 8]])          # 定义 2x2 矩阵 B\n",
    "\n",
    "print('A @ B =')                        # @ 表示矩阵乘法\n",
    "print(A @ B)                            # 矩阵乘法：行乘列再求和\n",
    "print('A*B =')                          # * 表示逐元素相乘\n",
    "print(A * B)                            # 逐元素乘法：对应位置直接相乘"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "3d5d37bd",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "原向量 [1 0] 旋转45度后 = [0.70710678 0.70710678]\n",
      "长度保持不变: |v|=1.000, |Rv|=1.000\n"
     ]
    }
   ],
   "source": [
    "# ---------- 2. 矩阵变换的几何意义：旋转 ----------\n",
    "theta = np.pi / 4                       # 旋转角度：45 度（弧度制）\n",
    "R = np.array([[np.cos(theta), -np.sin(theta)],   # 构造二维旋转矩阵\n",
    "              [np.sin(theta),  np.cos(theta)]])  # 作用是把向量绕原点逆时针旋转 theta\n",
    "\n",
    "v = np.array([1, 0])                    # 原始向量（沿 x 轴正方向的单位向量）\n",
    "v_rotated = R @ v                       # 用旋转矩阵作用于向量，得到旋转后的新向量\n",
    "\n",
    "print(f'原向量 {v} 旋转45度后 = {v_rotated}')\n",
    "print(f'长度保持不变: |v|={np.linalg.norm(v):.3f}, |Rv|={np.linalg.norm(v_rotated):.3f}')\n",
    "# 注：旋转是正交变换，只改变方向、不改变长度"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4fe3dbcd",
   "metadata": {},
   "source": [
    " 小实战：图片就是矩阵"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "85db0bfc",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "图片形状= (28, 28)\n",
      "非零像素数= 55\n"
     ]
    }
   ],
   "source": [
    "img = np.zeros((28, 28), dtype=np.uint8)   # 创建一个 28x28 的全零矩阵，类型为 8 位无符号整数（像素值 0~255）\n",
    "img[14, :] = 255                           # 把第 14 行（横线）所有列设为 255，即画一条白色横线\n",
    "img[:, 14] = 255                           # 把第 14 列（竖线）所有行设为 255，即画一条白色竖线\n",
    "\n",
    "print('图片形状=', img.shape)               # 查看矩阵形状\n",
    "print('非零像素数=', (img > 0).sum())        # 统计像素值大于 0 的个数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "ce439ee4",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "列表运算耗时: 0.1077 秒\n",
      "NumPy运算耗时: 0.0030 秒\n",
      "NumPy 比列表快 35.9 倍\n"
     ]
    }
   ],
   "source": [
    "# 作业1：numpy数组运算 vs 列表运算 计算速度\n",
    "\n",
    "import numpy as np\n",
    "import time\n",
    "\n",
    "# 数据规模：100万个元素\n",
    "N = 1_000_000\n",
    "\n",
    "# ---------- 1. Python 列表 ----------\n",
    "list_a = list(range(N))\n",
    "list_b = list(range(N))\n",
    "\n",
    "start = time.time()\n",
    "list_c = [a + b for a, b in zip(list_a, list_b)]   # 用列表推导式逐元素相加\n",
    "list_time = time.time() - start\n",
    "print(f'列表运算耗时: {list_time:.4f} 秒')\n",
    "\n",
    "# ---------- 2. NumPy 数组 ----------\n",
    "arr_a = np.arange(N)\n",
    "arr_b = np.arange(N)\n",
    "\n",
    "start = time.time()\n",
    "arr_c = arr_a + arr_b                              # 向量化加法，一行搞定\n",
    "numpy_time = time.time() - start\n",
    "print(f'NumPy运算耗时: {numpy_time:.4f} 秒')\n",
    "\n",
    "# ---------- 3. 速度对比 ----------\n",
    "print(f'NumPy 比列表快 {list_time / numpy_time:.1f} 倍')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9e45c411",
   "metadata": {},
   "source": [
    "为什么 NumPy 快这么多？\n",
    "\n",
    "对比项\tPython 列表\tNumPy 数组\n",
    "\n",
    "|对比项|Python 列表|NumPy 数组|\n",
    "|---|---|---|\n",
    "|数据类型|每个元素是独立 Python 对象|同类型数据连续存储|\n",
    "|内存布局|分散、指针跳转多|紧凑的连续内存块|\n",
    "|运算方式|解释器逐元素循环|C 语言底层向量化运算|\n",
    "|循环开销|每次操作都有 Python 层开销|循环在 C 层完成，开销极小|\n",
    "|代码写法|常用 for / 列表推导式|直接 `a + b`，无需显式循环|\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b4e680e1",
   "metadata": {},
   "source": [
    "关键概念：向量化（Vectorization）\n",
    "\n",
    "NumPy 的核心思想是 \"用数组整体操作代替显式循环\"：\n",
    "\n",
    "```python\n",
    "# ❌ 慢：显式循环\n",
    "result = []\n",
    "for i in range(N):\n",
    "    result.append(list_a[i] + list_b[i])\n",
    "\n",
    "# ✅ 快：向量化\n",
    "result = arr_a + arr_b\n",
    "```"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
