C语言小课堂:模运算

C语言小课堂:模运算
TANG JIAMEI模运算,又称模数、取模、取余数运算等,它得出一个数除以另一个数的余数。今天我们来一起了解一下在C语言中如何进行模运算。
一、知识点讲解
- 模运算是什么?
在C语言中,模运算(Modulo Operation)使用百分号 %
表示。它是一种二元运算符,用于计算两个整数相除后的余数。例如,a % b
表示 a
除以 b
的余数。
模运算的定义如下: 对于整数 a
和非零整数 b
, a % b
的结果 r
满足 a = q * b + r
,其中 q
是商,r
是余数。余数 r
的符号与被除数 a
的符号相同。其绝对值小于除数 b
的绝对值,即 0 <= |r| < |b|
。
示例:
10 % 3
的结果是 1
,因为 10 = 3 * 3 + 1
。
-10 % 3
的结果是 -1
,因为 -10 = -4 * 3 + 2
,但C语言中,余数的符号与被除数相同,所以 -10 = -3 * 3 - 1
,或者更准确地理解为 -10 / 3
的商为 -3
,余数为 -1
。
10 % -3
的结果是 1
,因为 10 = -3 * (-3) + 1
。
-10 % -3
的结果是 -1
,因为 -10 = -3 * 3 - 1
。
- 何时用?
模运算在编程中具有广泛的应用,尤其是在处理周期性、循环性或需要对数据进行分组、散列的场景。
何时用:
判断奇偶性: 当一个数 n
对 2
进行模运算时,如果结果为 0
,则 n
是偶数;如果结果为 1
或 -1
(取决于 n
的符号),则 n
是奇数。
限制数值范围(循环计数): 当需要一个变量在一个固定范围内循环时,模运算非常有用。例如,一个时钟的秒数从 0
到 59
循环,可以使用 (current_second + 1) % 60
来计算下一秒。
哈希函数: 在数据结构和算法中,模运算常用于构建哈希函数,将任意大的键映射到固定大小的哈希表索引中。
数字位操作: 获取一个数字的个位数、十位数等。例如 n % 10
可以得到 n
的个位数。
周期性任务调度: 在操作系统或嵌入式系统中,周期性任务的调度常常涉及模运算,以确定任务在某个时间周期内的执行点。
加密算法: 一些加密算法(如RSA)中会用到模幂运算。
为什么用: 模运算提供了一种简洁高效的方式来处理整数除法后的余数,这对于解决上述问题至关重要。它允许我们实现周期性行为、数据分组和边界限制,而无需复杂的条件判断或循环结构。
与关联知识点的联系与区别:
与除法运算符 /
的联系: 模运算与除法运算是紧密相关的。a / b
给出的是商,而 a % b
给出的是余数。两者共同构成了整数除法的完整结果。
与位运算符的联系: 对于 2
的幂次的模运算,有时可以用位运算代替以提高效率。例如,n % 2
等价于 n & 1
(对于非负数)。然而,位运算只适用于除数为 2
的幂次的情况,而模运算则适用于任意非零整数。
- 怎么用?
模运算的用法相对简单,但需要注意其操作数的类型和符号。
基本语法:result = operand1 % operand2;
其中 operand1
和 operand2
必须是整数类型(int
, long
, short
等)。如果操作数是浮点类型,编译器会报错。
示例代码:
1 |
|
注意事项:
除数( operand2
)不能为 0
,否则会导致运行时错误(除零错误)。
模运算结果的符号与被除数(operand1
)的符号相同。这是C语言标准规定的行为。
二、典型习题
- 选择题
一个整数 num
对 7
进行模运算,结果可能是以下哪个值?
A. 7
B. -7
C. 5
D. 8
- 判断题
表达式 (15 % 4) == (-15 % -4)
的结果为真(true)。
A. 对
B. 错
- 填空题
请填写 num % 10
表达式的计算结果,使其完成获取一个两位数 num
的个位数字的任务。例如,当 num
为 42
时,结果为 2
。
- 编程题
编写一个C语言程序,接收用户输入的一个正整数 n
,然后判断 n
是否为水仙花数。水仙花数是指一个三位数,其各位数字的立方和等于该数本身。例如, 153
是一个水仙花数,因为 1^3 + 5^3 + 3^3 = 1 + 125 + 27 = 153
。
要求:
程序应提示用户输入一个三位数。
使用模运算和除法运算分离出该三位数的百位、十位和个位。
计算各位数字的立方和。
判断并输出该数是否为水仙花数。
- 编程题
编写一个C语言程序,模拟一个简易的数字加密器。程序接收一个四位数的整数作为明文,然后对其进行加密。加密规则如下:
将明文的每个数字(个、十、百、千位)都加上 7
。
将每个数字的结果都对 10
取模,得到新的数字。
将新数字的千位和十位互换,百位和个位互换。
要求:
程序应提示用户输入一个四位数的整数。
使用模运算和除法运算分离出明文的各个数字。
按照加密规则进行计算和交换。
输出加密后的四位整数。
三、习题讲解
- 选择题
一个整数 num
对 7
进行模运算,结果可能是以下哪个值?
A. 7
B. -7
C. 5
D. 8
答案:C
解析:模运算 a % b
的结果 r
满足 0 <= |r| < |b|
,且 r
的符号与被除数 a
的符号相同。 在这里,除数是 7
,所以结果的绝对值必须小于 7
。
A. 7
的绝对值不小于 7
。
B. -7
的绝对值不小于 7
。
C. 5
的绝对值小于 7
,且可以是正数,符合条件。
D. 8
的绝对值不小于 7
。 因此, 5
是唯一可能的选项。
- 判断题
表达式 (15 % 4) == (-15 % -4)
的结果为真(true)。
A. 对
B. 错
答案:B
解析:首先计算 15 % 4
:15 = 3 * 4 + 3
,所以 15 % 4
的结果是 3
。
然后计算 -15 % -4
: C语言规定模运算结果的符号与被除数相同。-15 / -4
的商是 3
,余数是 -3
(因为 -15 = 3 * (-4) - 3
)。 所以 -15 % -4
的结果是 -3
。
比较 3 == -3
,结果为假(false)。因此,原表达式的结果为 错
。
- 填空题
请填写 num % 10
表达式的计算结果,使其完成获取一个两位数 num
的个位数字的任务。例如,当 num
为 42
时,结果为 2
。
答案: num % 10
解析:任何整数对 10
进行模运算,其结果就是该整数的个位数字。 例如:
42 % 10 = 2
123 % 10 = 3
7 % 10 = 7
这是因为当一个数被 10
除时,商是去掉个位数后的部分,余数就是个位数本身。
- 编程题
编写一个C语言程序,接收用户输入的一个正整数 n
,然后判断 n
是否为水仙花数。水仙花数是指一个三位数,其各位数字的立方和等于该数本身。例如, 153
是一个水仙花数,因为 1^3 + 5^3 + 3^3 = 1 + 125 + 27 = 153
。
代码实现:
1 |
|
解题思路:
输入与校验: 首先获取用户输入,并简单校验是否为三位数,以确保后续分离数字的逻辑正确。
分离数字:
个位: 利用 n % 10
可以直接得到 n
的个位数字。
去除个位: 利用 n = n / 10
可以将 n
的个位去除,使其变成一个两位数(或一位数)。
十位和百位: 重复上述过程,对新的 n
进行 n % 10
得到十位,再 n = n / 10
得到百位。
计算立方和: 将分离出的三个数字分别求立方,然后相加。
判断: 将计算出的立方和与原始输入的数进行比较,如果相等,则是水仙花数。
- 编程题
编写一个C语言程序,模拟一个简易的数字加密器。程序接收一个四位数的整数作为明文,然后对其进行加密。加密规则如下:
将明文的每个数字(个、十、百、千位)都加上 7
。
将每个数字的结果都对 10
取模,得到新的数字。
将新数字的千位和十位互换,百位和个位互换。
代码实现:
1 |
|
解题思路:
输入与校验: 获取用户输入,并确保其为四位数。
分离数字: 利用除法和模运算的组合,从明文中逐一提取出千位、百位、十位和个位。
plaintext % 10
得到个位。
(plaintext / 10) % 10
得到十位。
(plaintext / 100) % 10
得到百位。
plaintext / 1000
得到千位。
加密计算: 对每个分离出的数字,按照规则 (digit + 7) % 10
进行计算,得到加密后的新数字。
数字交换与重组: 根据交换规则,将新得到的四个数字重新组合成一个四位数。需要注意的是,这里是位置的交换,而不是数字本身的交换。新数字的千位是原先的十位加密结果,新数字的百位是原先的个位加密结果,以此类推。
新的千位是 e3
(原十位加密结果)
新的百位是 e4
(原个位加密结果)
新的十位是 e1
(原千位加密结果)
新的个位是 e2
(原百位加密结果) 最后将它们乘以相应的权重(1000, 100, 10, 1)并相加。
你总以为时间线是笔直向前,却不曾料想,在某个不经意的节点,一切又回到了起点,那不是停滞,而是另一种周而复始的秩序,每一次归零,都蕴含着新的可能。