取模运算%和按位与&

最近在研究 Redis 源码,发现一些平时不怎么用的编码习惯,感觉挺有趣,记录下

function isOdd1($num) {
    return ($num % 2) == 1;
}

function isOdd2($num) {
    return ($num & 1) == 1;
}

以上两个方法都是用来判断一个数是否为奇数,但是用到的操作符不同,有什么区别 ?

%:取模操作符是基于 十进制(人类思维) 的一种取模方式,如:11 % 4 = 3,常用在各种操作中,可判断奇偶,也可以用在哈希中,如:11 % 8 = 3,落在第 3 个槽中,即 $arr[3-1] 中

&:按位与是基于 二进制 的,如:11 & 1 = 00001011 & 00000001 = 1,常用在 哈希 中,如计算出的 哈希 值为 11,哈希槽个数为 8,则 11 & (8-1) = 00001011 & 00000111 = 00000011 = 2,即 $arr[2] 中

虽然只是符号的差别,但是性能差距还是蛮大的,有 10 倍的差距(可能体现不明显),但有如下好处:

1.积少成多,如果处处都追求这种高效的方式,整体代码质量可能也会更高,放到 C 语言也是如此,像 Redis 这种追求超高性能的软件,一定会用位运算的

2.如果别人看到了你的代码是这样,一定会觉得有点高大上的,毕竟一般很少有人用

但也有坏处:

1.由于非人类语言,所以有可能用出错误

2.别人看你的代码,有可能需要绕个弯才能懂

哈哈~

<think>好的,用户想了解C语言中模运算的应用场景用法,特别是实例。首先,我需要明确模运算在C语言中的基本定义语法。模运算符是%,它返回两个数相除后的余数。例如,5%3的结果是2,因为5除以3商1余2。需要注意,当操作数为负数时,结果符号依赖于编译器,但C99标准规定结果符号与被除数相同,比如-5%3在C99中是-2,而5%-3则是2。不过实际编程中应尽量避免负数的情况,以免出现兼容性问题。 接下来是应用场景。常见的场景包括判断奇偶性,比如用n%2是否等于0来判断是否为偶数。另一个是循环队列或环形缓冲区的索引计算,通过来循环利用空间。还有周期性任务调度,比如每5次执行一次操作,可以用计数器%5是否为0来控制。此外,生成特定范围的随机数时,可以用rand()%n来得到0到n-1之间的数。 然后需要给出具体的使用实例。例如,判断闰年的条件之一是年份能被4整除但不能被100整除,或者能被400整除,可以用模运算实现。另外,时间转换如将总秒数转换为小时、分钟、秒,也可以用来分解各个部分。例如,总秒数total_seconds%60得到剩余的秒数,再除以60得到分钟,依此类推。 需要注意的问题包括处理负数的余数问题,以及除数不能为0,否则会导致运行时错误。同时,模运算的效率通常较高,但在性能敏感的场景中仍需评估。 最后,根据用户提供的引用资料,检查是否有相关内容可以引用。例如,引用[4]提到C语言中的运算符写法,可以引用说明乘除符号的不同,但用户的问题是关于,所以可能引用较少。不过引用[3]提到位运算优化,可能与的位运算替代方法有关,比如用位操作代替2的运算,但用户可能更关注直接的应用,所以这部分可以作为扩展提及。 总结回答结构:先介绍模运算符的语法基本用法,然后详细列举应用场景并给出代码实例,最后指出注意事项常见错误,并引用相关资料中的相关内容。确保使用正确的LaTeX格式,如变量用$n \% 2$,独立公式用$$...$$,同时生成相关问题。</think>### C语言模运算详解 #### 一、基本语法与定义 模运算符`%`用于计算两个整数相除后的余数,满足公式: $$a \% b = a - b \times \left\lfloor \frac{a}{b} \right\rfloor$$ 其中`b ≠ 0`,结果符号**与`a`相同**(C99标准)[^4]。 #### 二、核心应用场景与实例 1. **奇偶性判断** ```c int num = 7; if (num % 2 == 0) { printf("偶数\n"); } else { printf("奇数\n"); // 输出结果 } ``` 2. **循环队列索引控制** ```c #define QUEUE_SIZE 10 int index = 12; int actual_pos = index % QUEUE_SIZE; // 实际存储位置为2 ``` 3. **周期性任务触发** ```c for (int i=1; i<=100; i++) { if (i % 5 == 0) { // 每5次触发 printf("执行维护操作\n"); } } ``` 4. **时间格式转换** ```c int total_seconds = 3661; int hours = total_seconds / 3600; int minutes = (total_seconds % 3600) / 60; int seconds = total_seconds % 60; // 得到1小时1分1秒 ``` #### 三、特殊场景处理 1. **负数**(C99标准) ```c printf("%d\n", -7 % 3); // 输出-1(符号与被除数-7相同) printf("%d\n", 7 % -3); // 输出1(符号与被除数7相同) ``` 2. **进制转换** ```c void decimal_to_binary(int n) { if (n > 1) decimal_to_binary(n/2); printf("%d", n % 2); // 通过二进制位 } ``` #### 四、注意事项 1. **零除数保护** ```c int a = 5, b = 0; // if (b != 0) { ... } // 必须添加判断避免崩溃 ``` 2. **性能优化技巧** 对于$2^n$的模运算,可用位运算加速: ```c x % 8 → x & 0x07 // 等效但更快[^3] ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值