【C语言】数据运算
在C语言(Keil C51 ) 中,“数据运算”有以下几类:
一、算术运算
1. 加减乘除 取余
运算 | 运算符 | 示例 | 结果 |
|---|---|---|---|
加法 |
|
|
|
减法 |
|
|
|
乘法 |
|
|
|
除法 |
|
|
|
取余 |
|
|
|
1unsigned char a = 7;2unsigned char b = 3;34unsigned char sum = a + b; // 105unsigned char difference = a - b; // 46unsigned char product = a * b; // 217unsigned char quotient = a / b; // 28unsigned char remainder = a % b; // 1
2. 正号与负号
运算 | 运算符 | 示例 |
|---|---|---|
保持正值 |
|
|
改变正负 |
|
|
1int a = 10;2int b = -a; // b = -10
3. 自增与自减
运算 | 运算符 | 示例 | 含义 |
|---|---|---|---|
自增 |
|
|
|
自减 |
|
|
|
1unsigned char a = 7;2unsigned char b;34a++; // a = 85a--; // a = 767++a; // a = 88--a; // a = 7910b = a++; // 先是 b = 7 然后 a = 811b = a--; // 先是 b = 8 然后 a = 71213b = ++a; // 先是 a = 8 然后 b = 814b = --a; // 先是 a = 7 然后 b = 7
二、二进制 按位运算
1. 按位与 &
a & b 将两个数据的每一位进行“与”操作:当二者此位都是 1,则结果的此位是 1,否则为 0。
1 0000 11002& 0000 10103------------4 0000 1000
2. 按位或 |
a | b 将两个数据的每一位进行“或”操作:当二者此位任意一个是 1,则结果的此位是 1,否则为 0。
1 0000 11002| 0000 10103------------4 0000 1110
3. 按位异或
a ^ b 将两个数据的每一位进行“异或”操作:当二者此位有且只有一个是 1,则结果的此位是 1,否则为 0。
1 0000 11002^ 0000 10103------------4 0000 0110
4. 按位取反
~a 将数据的每一位都取反,0变1,1变0;
10000 11002取反31111 0011
三、二进制 移位运算
1. 左移
a << n 将所有二进制位向左移动 n 位,右侧补 0,左侧移出去的数据丢失。
1a = 0010 110123a << 4:451101 0000
2. 右移
a >> n 将所有二进制位向右移动 n 位,左侧补 0,右侧移出去的数据丢失。
1a = 0010 110123a >> 4:450000 0010
3. 循环左移 循环右移
循环位移函数由Keil C51 提供的,普通移位会丢弃被移出去的二进制位,而循环移位会把移出去的数据重新放到另一端。
函数 | 作用 |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
函数名称中的 c、i、l 分别代表 unsigned char、unsigned int 和 unsigned long , ro 代表循环,l 和 r 分别代表 左 和 右。
1a = 1000 000123a = _crol_(a, 1);45结果为 0000 0011
四、比较运算
比较运算用于比较两个数据的大小或是否相等。
运算 | 运算符 | 示例 |
|---|---|---|
等于 |
|
|
不等于 |
|
|
大于 |
|
|
小于 |
|
|
大于等于 |
|
|
小于等于 |
|
|
1if (a >= 10)2{3 // a大于或等于104}
五、逻辑运算
逻辑运算通常用于组合多个判断条件。
运算 | 运算符 | 含义 |
|---|---|---|
逻辑与 |
| 两个条件都成立 |
逻辑或 |
| 两个条件至少有一个成立 |
逻辑非 |
| 条件取反 |
1if ((a > 0) && (a < 10))2{3 // a大于0并且小于104}56if ((a == 1) || (b == 1))7{8 // 至少有一个条件成立9}1011if (!a)12{13 // a等于0时成立14}
六、复合赋值运算
复合赋值就是“完成一次运算,并把结果重新存入变量”。
运算符 | 等价写法 |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
七、条件运算符
条件运算符也叫三目运算符:条件 ? 结果1 : 结果2,如果条件成立,则返回结果1,如果条件不成立,则返回结果2。
1max = (a > b) ? a : b;2// 等价于3if (a > b) {4 max = a;5}6else {7 max = b;8}
八、强制类型转换
强制类型转换 可以在计算过程中将某个类型的数据强制当做另一种类型的数据处理。
1unsigned char a = 7;2unsigned char b = 2;3float result;45result = a / b; // 结果是 3,因为整数除法,结果只保留整数6result = (float)a / b; // 结果是 3.5,因为此时 a 当做浮点数,因而进行的是浮点数除法
九、常用数学函数
大多数数学函数需要包含#include <math.h>
1. 绝对值
函数 | 作用 |
|---|---|
| 求 |
| 求 |
| 求浮点数绝对值 |
1int a = abs(-10); // 102long b = labs(-1000L); // 10003float c = fabs(-3.14); // 3.14
2. 取整
函数 | 作用 |
|---|---|
| 向上取整 |
| 向下取整 |
1float a = ceil(3.2); // 结果:4.02float b = ceil(3.8); // 结果:4.03float c = ceil(-3.2); // 结果:-3.045float a = floor(3.2); // 结果:3.06float b = floor(3.8); // 结果:3.07float c = floor(-3.2); // 结果:-4.0
3. 浮点数取余
浮点数不能使用 %取余,可以使用 fmod()
1float a = fmod(7.5, 2.0); // 结果:1.52float b = fmod(8.0, 3.0); // 结果:2.0
4. 平方根
sqrt(x) 用于计算一个数的平方根。
1float a = sqrt(16.0); // 结果:4.02float b = sqrt(25.0); // 结果:5.03float c = sqrt(2.0); // 结果:约1.41445// 通常不能对负数进行普通的平方根运算:67float a = sqrt(-1.0); // 结果:无效浮点数
5. 乘方运算
pow(x, y) 用于计算 x 的 y 次方。
1float a = pow(2.0, 3.0); // 结果:8.02float b = pow(10.0, 2.0); // 结果:100.03float c = pow(9.0, 0.5); // 结果:3.0
6. 三角函数
函数 | 作用 |
|---|---|
sin() | 计算正弦值 |
cos() | 计算余弦值 |
tan() | 计算正切值 |
这些函数接收的角度单位是弧度,而不是通常使用的角度。
1#define PI 3.141592623float a = sin(PI / 2); // 结果:约1.04float b = cos(0); // 结果:1.05float c = tan(PI / 4); // 结果:约1.067如果已知的是角度,可以先转换成弧度:89#define PI 3.14159261011float angle = 90.0;12float radian = angle * PI / 180.0; // 结果:约1.570813float value = sin(radian); // 结果:约1.0
7. 反三角函数
函数 | 作用 |
|---|---|
asin() | 反正弦 |
acos() | 反余弦 |
atan() | 反正切 |
atan2() | 根据横纵坐标计算方向角 |
1#define PI 3.141592623float a = asin(1.0); // 结果:约1.5708弧度,也就是90°4float b = acos(0.0); // 结果:约1.5708弧度,也就是90°5float c = atan(1.0); // 结果:约0.7854弧度,也就是45°6float d = atan2(1.0, 1.0); // 结果:约0.7854弧度,也就是45°78将弧度转换成角度:910#define PI 3.14159261112float radian = atan(1.0); // 结果:约0.7854弧度13float angle = radian * 180.0 / PI; // 结果:约45.0°
8. 指数和对数
函数 | 作用 |
|---|---|
exp() | 计算以 e 为底的指数 |
log() | 计算以 |
log10() | 计算以 |
1exp():计算以 e 为底的指数2float a = exp(0.0); // 结果:1.03float b = exp(1.0); // 结果:约2.7184float c = exp(2.0); // 结果:约7.3895log():计算自然对数67log() 计算的是以 e 为底的对数。89float a = log(1.0); // 结果:0.010float b = log(2.71828); // 结果:约1.011log10():计算常用对数1213log10() 计算的是以 10 为底的对数。1415float a = log10(10.0); // 结果:1.016float b = log10(100.0); // 结果:2.017float c = log10(1000.0); // 结果:3.01819对数函数的参数必须大于 0:2021float a = log(0.0); // 结果:无效或趋近负无穷22float b = log(-1.0); // 结果:无效浮点数
9. 随机数
rand() 用于产生一个伪随机整数。
1unsigned int a = rand(); // 结果:一个伪随机整数23可以使用 % 限制随机数范围:45unsigned int a = rand() % 10; // 结果:0~9之间的整数6unsigned int b = rand() % 6 + 1; // 结果:1~6之间的整数7unsigned int c = rand() % 100 + 1; // 结果:1~100之间的整数89srand() 可以设置伪随机数的种子:1011srand(123); // 结果:设置随机数种子为12312unsigned int a = rand(); // 结果:由当前C51库实现决定的伪随机数1314使用相同的种子,通常会产生相同的伪随机数序列。
注意事项
51 单片机通常没有专门的浮点运算硬件,因此下面这些函数主要通过软件完成:
sqrt(); pow(); sin(); cos(); tan(); log();
它们虽然使用方便,但会增加程序体积,并占用较多运算时间。
因此,在普通的 51 单片机程序中:
- 简单计算优先使用整数运算。
- 乘以或除以 2 的整数次幂,可以考虑移位运算。
- 三角函数和开方运算尽量不要放在高频循环或中断函数中。
- 对运算速度要求较高时,可以使用查表法或定点数运算。