当前位置: 首页 > news >正文

模运算的基本性质

问题引入

今天在刷题的时候遇到了一个问题,为什么((x + y) % p + y) % p等价于(x + y + y) % p?
这就要了解模运算的性质,之前其实已经学过模运算的分配律、结合律等等了,但是太懒了就没有总结,看来还是得总结一下。。。

模运算的基本性质

首先了解预备知识:

  1. 模可以加、减、乘、幂,但不能直接除。
  2. 在模运算下,你可以“先模后加、减、乘、幂”,也可以“合起来运算完完再模”,因为加、减、乘、幂和模运算是兼容的,换句话说:模可以出现在运算的任何位置

加法性质

(a % m + b % m) % m ≡ (a + b) % m

模可以分配到加法里,也可以从加法里提取出来,这就是分配律和结合律

减法性质

错误写法: (a % m - b % m) % m ≡ (a - b) % m

注意这样有可能得到负数,比如(3 % 5 - 7 % 5) % 5 的结果本来是 (3 - 2) % 5 = 1
但是如果根据公式来计算
(3 % 5 - 7 % 5) % 5 = (3 - 7) % 5 = -4 % 5 = 1

乘法性质

(a % m * b % m) % m ≡ (a * b) % m

幂运算性质(可递推)

(a^k) % m ≡ ((a % m)^k) % m

📌这是快速幂的基础

传递性(等价替换)

a ≡ b (mod m),则 f(a) ≡ f(b) (mod m)

只要 f 是由加减乘幂构成的表达式就可以替换

同余传递性

如果 a ≡ b (mod m),且 c ≡ d (mod m)
则 a + c ≡ b + d (mod m)
a - c ≡ b - d (mod m)
a * c ≡ b * d (mod m)

取模分配律(可以提前或延后取模)

(a + b) % m ≡ ((a % m) + (b % m)) % m
(a - b) % m ≡ ((a % m) - (b % m) + m) % m
(a * b) % m ≡ ((a % m) * (b % m)) % m

一个防负数的技巧(模加模)

((a % m) + m) % m

负数取模的结果

1. 商向零取整 (Truncated Division)

  • 适用语言: C/C++/Java/JavaScript
  • 规则: 结果的符号与被除数(第一个数)相同
  • 公式:
    a % b = a - b × trunc(a / b)
    trunc表示向零取整,即直接截断小数部分)
-7 % 3 = -1   // 因为 -7 ÷ 3 = -2.333... → trunc(-2.333) = -2 → -7 - (3 × -2) = -1
7 % -3 = 1    // 7 ÷ -3 = -2.333... → trunc(-2.333) = -2 → 7 - (-3 × -2) = 1
-7 % -3 = -1  // -7 ÷ -3 = 2.333... → trunc(2.333) = 2 → -7 - (-3 × 2) = -1

2. 商向负无穷取整 (Floored Division)

  • 适用语言: Python/Ruby

  • 规则: 结果的符号与除数(第二个数)相同,且结果非负

  • 公式:
    a % b = a - b × floor(a / b)
    floor表示向下取整)

-7 % 3 = 2    # 计算过程:# -7 ÷ 3 = -2.333... → floor(-2.333) = -3# -7 - (3 × -3) = 27 % -3 = -2   # 7 ÷ -3 = -2.333... → floor(-2.333) = -3# 7 - (-3 × -3) = -2-7 % -3 = -1  # -7 ÷ -3 = 2.333... → floor(2.333) = 2# -7 - (-3 × 2) = -1

3. 数学上的模运算(同余)

数学中,模运算的结果通常是非负的(与Python规则一致),例如:
-7 ≡ 2 (mod 3)
因为 -7 + 3 × 3 = 2

floortrunc 函数对比

1. 定义对比

函数行为描述数学表示
floor向负无穷方向取整(返回 ≤ 原数的最大整数)floor(x) = ⌊x⌋
trunc向零方向取整(直接截断小数部分)trunc(x) = { ⌊x⌋ (x≥0), ⌈x⌉ (x<0) }

2. 具体行为

(1) 正数的情况
输入x = 3.7

  • floor(3.7) = 3
  • trunc(3.7) = 3
    (两者结果相同)

(2) 负数的情况
输入x = -2.3

  • floor(-2.3) = -3 (向更小的整数方向取整)
  • trunc(-2.3) = -2 (直接截断小数部分,向零靠近)

3. 关键区别

  • 对于正数:两者行为一致
  • 对于负数
    • floor:向更小的整数取整(-2.3 → -3)
    • trunc:向零取整(-2.3 → -2)

4. 应用场景

  • floor:用于需要保证结果≤原数的场景(如分页计算)
  • trunc:用于需要快速截断小数部分的场景(如金融取整)

注:⌊ ⌋表示向下取整,⌈ ⌉表示向上取整

回到问题

为什么((x + y) % p + y) % p等价于(x + y + y) % p?

原式((x + y) % p + y) % p相当于

  • 先对 (x + y) 取了模
  • 再加一个 y
  • 再取模

这就等价于把所有加数凑一起 (x + y + y) 后整体取模,因为(x + y) 取模之后的结果再取模结果是不变的,(x + y)不管取几次模结果都是一样的,只要有一次取模就行了,内层的取模运算我们就可以去掉,所以可以转换成(x + y + y) % p
这样以来了解本质后,就可以在原来的加法性质进一步扩展,不仅仅只有 (a % m + b % m) % m 的时候才等价于 (a + b) % m。同样地 (a % m + b ) % m(a + b % m) % m 都是等价于 (a + b) % m
的。

相关文章:

  • 重新定义“边缘”:边缘计算如何重塑人类与数据的关系
  • 记一次内存泄漏
  • 如何在 .NET 环境中使用 Npgsql 驱动连接 KaiwuDB
  • 深入探究 TCP 与 UDP 协议:原理、特性及应用
  • java CountDownLatch用法简介
  • 华为纯血 卓易通 使用记录
  • 【JavaEE初阶】多线程重点知识以及常考的面试题-多线程进阶(二)
  • Yakit的免配置浏览器不是内置浏览器
  • 【MySQL】前缀索引、索引下推、访问方法,自适应哈希索引
  • API平台(API网关)的API安全保障机制
  • 在云服务器的 Linux 系统中安装 Python 的步骤(以常见发行版 Ubuntu/CentOS 为例)
  • Linux的应用领域,Linux的介绍,VirtualBox和Ubuntu的安装,VMware的安装和打开虚拟机CentOS
  • 李宏毅NLP-4-语音识别part3-CTC
  • C 语言结构体中的函数指针与 Kotlin 高阶函数的对比
  • 语音合成(TTS)从零搭建一个完整的TTS系统-第一节-效果演示
  • AIGC-十款知识付费类智能体完整指令直接用(DeepSeek,豆包,千问,Kimi,GPT)
  • 《MAmmoTH2: Scaling Instructions from the Web》全文翻译
  • 智慧城市像一张无形大网,如何紧密连接你我他?
  • HOJ PZ
  • 【玩转全栈】—— Django+vue3+讯飞星火API 实现前端页面实时AI答复
  • 怎样做二维码链接到网站上/深圳营销型网站定制
  • 表情包在线制作网站/链接转二维码
  • 前端开发和后端开发哪个好些/seo研究中心培训机构
  • 自建网站注册域名很有必要/免费的个人主页网页制作网站
  • 专业医院网站建设/抖音代运营公司
  • 做网站济南西/购物网站网页设计