别再死记硬背了!用Python和JavaScript代码实例,5分钟搞懂模运算的加减乘除规律
别再死记硬背了用Python和JavaScript代码实例5分钟搞懂模运算的加减乘除规律模运算在编程中无处不在从简单的循环索引到密码学算法都离不开它。但很多初学者面对那些看似复杂的模运算公式时往往选择死记硬背——这不仅痛苦而且容易遗忘。本文将用Python和JavaScript两种语言的代码实例带你在实际运行中直观理解模运算的规律告别枯燥的公式记忆。1. 模运算基础从概念到代码验证模运算本质上是求余数的运算在编程中用%符号表示。但它的行为有时会出乎意料特别是涉及负数时。让我们先用代码验证几个基本特性# Python中的模运算示例 print(17 % 5) # 输出2因为17÷5商3余2 print(-3 % 5) # 输出2这是Python的特性// JavaScript中的模运算 console.log(17 % 5); // 2 console.log(-3 % 5); // -3与Python不同关键发现Python的%总是返回与除数同号的余数JavaScript的%则保留被除数的符号两种语言中(a % b)的结果绝对值都小于b提示跨语言开发时负数的模运算差异是常见bug来源务必注意。2. 模运算的四大基本规律验证模运算的加减乘除规律看起来像普通算术但需要验证才能确信。让我们用代码测试这些规律是否成立。2.1 加法分配律公式(A B) % M (A % M B % M) % Mdef test_add_rule(a, b, m): left (a b) % m right (a % m b % m) % m return left right print(test_add_rule(17, 23, 5)) # True print(test_add_rule(-4, 9, 7)) # True2.2 乘法分配律公式(A * B) % M [(A % M) * (B % M)] % Mfunction testMulRule(a, b, m) { const left (a * b) % m; const right ((a % m) * (b % m)) % m; return left right; } console.log(testMulRule(12, 7, 5)); // true console.log(testMulRule(-3, 8, 6)); // true2.3 幂运算规律公式(A^n) % M [(A % M)^n] % Mdef test_pow_rule(a, n, m): left pow(a, n) % m right pow(a % m, n) % m return left right print(test_pow_rule(3, 4, 7)) # True print(test_pow_rule(5, 3, 11)) # True2.4 结合律验证function testAssociative(a, b, c, m) { const left ((a b) % m c) % m; const right (a (b c) % m) % m; return left right; } console.log(testAssociative(4, 7, 2, 5)); // true3. 模逆元密码学中的关键概念模逆元在RSA等加密算法中至关重要。数a在模m下的逆元b满足(a * b) % m 13.1 暴力搜索法求逆元def find_mod_inverse(a, m): for b in range(1, m): if (a * b) % m 1: return b return None # 不存在逆元 print(find_mod_inverse(3, 7)) # 输出5因为3*515≡1 mod73.2 使用扩展欧几里得算法更高效的算法实现function extEuclid(a, b) { if (b 0) return [a, 1, 0]; const [gcd, x1, y1] extEuclid(b, a % b); const x y1; const y x1 - Math.floor(a / b) * y1; return [gcd, x, y]; } function modInverse(a, m) { const [gcd, x, y] extEuclid(a, m); return gcd 1 ? (x % m m) % m : null; } console.log(modInverse(3, 7)); // 54. 实战应用循环队列与哈希函数理解了模运算规律后让我们看两个实际应用。4.1 实现循环队列class CircularQueue: def __init__(self, size): self.size size self.queue [None] * size self.head self.tail 0 def enqueue(self, item): next_pos (self.tail 1) % self.size if next_pos self.head: raise Exception(Queue is full) self.queue[self.tail] item self.tail next_pos def dequeue(self): if self.head self.tail: raise Exception(Queue is empty) item self.queue[self.head] self.head (self.head 1) % self.size return item4.2 简单哈希函数实现class SimpleHashTable { constructor(size) { this.size size; this.table new Array(size); } hash(key) { let hash 0; for (let i 0; i key.length; i) { hash (hash * 31 key.charCodeAt(i)) % this.size; } return hash; } set(key, value) { const index this.hash(key); this.table[index] value; } }模运算的这些特性在实际编程中远比我们想象的更有用。比如在开发一个轮播组件时用current_index % total_slides就能实现无限循环的效果在处理大型数组的分块操作时模运算可以帮助我们均匀分配任务。