C语言知识库

浏览

4.3k

被索引

4
  • 1
  • 0
  • 0
  • C语言算数运算符细节总结

  • 孤寂Solitude
  • 598
  • 2026-05-11 23:36
  • 一、整数除法:结果向零取整(截断)

    规则:两个整数相除,结果只保留整数部分,直接丢弃小数部分(不四舍五入)。C99标准后规定为向零取整

    printf("%d\n", 10 / 3);   // 输出 3  (3.333… 截断)
    printf("%d\n", 10 / 2);   // 输出 5
    printf("%d\n", 9 / 4);    // 输出 2
    printf("%d\n", -10 / 3);  // 输出 -3 (-3.333… 向零取整得 -3)
    printf("%d\n", 10 / -3);  // 输出 -3

    注意:即使两个整数非常接近,结果依然是整数,不会自动变成浮点数。


    二、浮点数与整数混合运算:整型自动提升为浮点型

    规则:只要 + - * / 任一操作数是浮点类型(float / double),另一个整型操作数会被隐式转换为浮点类型,整个运算变为浮点运算,结果也是浮点类型。

    printf("%f\n", 10 / 3.3);   // 输出 3.030303 (数字10 → 10.0)
    printf("%f\n", 10.0 / 3);   // 输出 3.333333 (数字3 → 3.0)

    格式说明printf 输出 double 时可用 %f%lf(效果相同);scanf 读取 double 时必须用 %lf


    三、浮点数运算可能不精确

    原因:计算机使用二进制浮点数(IEEE 754),很多十进制小数(如 0.1, 1/3)无法精确表示,只能近似存储。

    典型示例

    printf("%.20f\n", 0.1 + 0.2);
    // 期望 0.3,实际输出 0.30000000000000004440...
    
    printf("%.20f\n", 10.0 / 3.0);
    // 期望 3.3333333333...,实际输出类似 3.33333333333333348136
    
    double sum = 0.0;
    for (int i = 0; i < 10; i++) sum += 0.1;
    printf("%.20f\n", sum);
    // 期望 1.0,实际输出 0.99999999999999988898...

    注意:并不是所有浮点运算都会出现明显误差。例如您代码中的:

    printf("%.30lf\n", 6.666666666666666 + 3.333333333333333);

    在实际运行时,由于这两个数都是有限位小数(小数点后15位),且和正好是 9.999999999999999,它非常接近 10.0,根据浮点舍入规则,大多数编译器会直接输出 10.000000000000000000000000000000(精确的 10.0)。这并不矛盾——浮点误差仅发生在无法精确表示的情况下

    应对方法(现阶段了解即可)

    • 比较浮点数时不要直接用 ==(但尚未学 if,先知道这个原则)。
    • 金额计算尽量用整数(比如以“分”为单位)。
    • 输出时用 %g 或限制小数位数可以减少显示上的困扰。

    四、除法(/)的边界:除数不能为 0

    规则:整数或浮点除法,除数都不能为 0(和数学一样)。

    后果:程序会崩溃(运行时错误),甚至可能导致未定义行为。

    现阶段做法:在写代码时主动保证除数不为0。例如:

    int a = 10;
    int b = 2;
    // 确保 b !=(不等于) 0 再计算
    printf("%d\n", a / b);   // 安全
    注意:您尚未学习 if,因此无法在代码中做判断,只能靠编程时自己注意。以后学了条件判断,可以加上保护。

    五、取余运算符(%):只适用于整数

    5.1 基本规则

    • 操作数必须是整数:不能对 float / double 使用 %(编译错误)。
    • 结果符号:与被除数(第一个操作数)的符号相同。
    • 恒等式:a % b = a - (a / b) * b,其中 / 是整数除法(向零取整)。

    5.2 示例

    //与被除数(第一个操作数)的符号相同。
    printf("%d\n",  10 %  3);   //  1
    printf("%d\n", -10 %  3);   // -1
    printf("%d\n",  10 % -3);   //  1
    printf("%d\n", -10 % -3);   // -1

    记忆口诀:余数正负看左边。

    5.3 取余也不能为 0

    a % 0 同样导致程序崩溃(除零错误)。

    5.4 典型应用

    • 判断奇偶:n % 2 == 0 为偶数,n % 2 == 1 或 n % 2 == -1 为奇数(注意负数)。
    • 循环数组下标(以后学到数组时会用到)。
    • 拆解数字的每一位(见第六部分)。

    六、综合练习:拆解三位整数的个位、十位、百位

    int num;
    printf("请输入一个三位整数:");
    scanf("%d", &num);
    
    // 以 num = 230 为例,运算步骤如下:
    // 1. 个位:230 除 10 商 23 余 0
    // 2. 十位:230 除 10 商23 % 10 商 2 余 3
    // 3. 百位:230除100 商2 余 (正常情况下:2.3)但在c语言当中整数运算会将小数抛弃
    
    int ge  = num % 10;          // 个位
    int shi = num / 10 % 10;     // 十位
    int bai = num / 100 % 10;         // 百位
    
    //千位:num / 1000 % 10;
    
    printf("个位:%d\n十位:%d\n百位:%d\n", ge, shi, bai);

    推导(以 230 为例)

    • 个位:230 % 10 = 0
    • 十位:230 / 10 = 23,然后 23 % 10 = 3
    • 百位:230 / 100 = 2(整数除法截断)

    负数情况:公式依然适用,但余数符号与被除数一致。
    例如 num = -230 → 个位 0,十位 -3,百位 -2。若希望得到非负余数,可以先取绝对值(使用 abs 函数,需 #include ),但现阶段可以不考虑。

    扩展到任意多位数

    • 获取第 n 位(个位为第 0 位):digit = (num / (int)pow(10, n)) % 10(需 #include
    • 或者用循环(以后学了循环再实现):每次 %10 得到最低位,然后 /10 去掉最低位。

    七、类型转换

    在C语言当中一共有两种类型转换方式,分别为:隐式转换强制转换

    7.1 隐式转换(自动类型提升)

    先说第一个隐式转换,此时你会好奇什么是隐式转换?

    隐式转换就是编译器自动完成的类型转换。

    隐式转换小结

    取值范围:char < short < int < long < long long < float < double

    什么时候转换?

    不同的类型进行计算、赋值等操作、就会触发隐式转换

    比如:

    int a = 12;
    long b = 2;
    int num = a + b; //那么此时是什么类型呢?
    
    printf("%d",num);

    你可能会说当然是int类型啊,其实不是 此时 从变量类型int和long开始进行比较,比较谁的范围大,根据上述的取值范围 变量a(int类型)此时与变量b(long)进行转换 变量a明显取值范围要小于long类型,那么int类型就会自动的提升为long类型。

    所以此时变量num计算出最后的结果就是long类型。

    当然在日常写代码当中为了提升整体的阅读效果int num = a + b; 就不推荐这样写法别人一看什么玩意,还要自己去想,作为一名合格的程序员应该写成:

    //明确告诉别人此时隐式转换的结果
    //不推荐
    int num = a + b;
    //推荐
    long num = a + b;

    转换规则:

    01、取值范围小的和取值范围大的进行运算,小的会先提升为大范围,然后再进行计算

    比如:

    int b1 = 5;
    double b2  = 10;
     //此时如果将两者进行计算的话 int(小范围)就会先提升为double类型。因为double的取值范围是要大于int类型的

    02、char   short类型的数据在运算的过程中,都会先直接提升为int类型,然后再进行计算


    7.2 强制转换

    取值范围:char < short < int < long < long long < float < double

    什么时候转换?

    大的赋值给小范围的时候,就需要强制转换。

    格式:

    想要转什么类型,就在前面的小括号填写什么类型即可。

    比如: short  i = (short)b

    强制转换的弊端:

    可能导致数据错误

    比如:

    //1. 数据溢出(超出目标类型的范围)
    
    int big = 100000;          // 10万,在 int 范围内
    short small = (short)big;  // short 最大约 32767,10万远超范围
    printf("%d\n", small);     // 输出结果不可预料(通常发生截断或环绕)
    
    //2. 精度丢失(小数部分被截断)
    
    double pi = 3.1415926;
    int ipi = (int)pi;        // 结果为 3,小数部分直接丢弃(不是四舍五入)
    printf("%d\n", ipi);      // 输出 3

    隐式转换是编译器“自动地、安全地”把小类型变大;强制转换是程序员“手动地、有风险地”把大类型变小(或临时改变解释方式)。

    具体展开对比一下:

    对比维度隐式转换(自动类型提升)强制转换(显式转换)
    触发者编译器自动完成程序员手动写代码 (类型)
    转换方向总是从取值范围小取值范围大提升常用于将取值范围大的类型转换为的类型
    安全性安全,不会丢失数据或精度(提升时)有风险,可能发生数据溢出或精度丢失
    何时发生混合运算、赋值、函数传参等场景需要临时改变类型、强制截断、满足接口要求时
    典型例子10.0 / 3 → 3 提升为 double,结果变 double(int)3.14 → 丢弃小数得 3
    是否可控不可控,由类型提升规则决定完全由程序员控制

    注意:

    此时你会好奇的说那么像char这种类型又是怎么转换的呢? 虽然你已经知道char类型会自动提升为int类型那么它们是怎么转换的?

    前面我们知道ASCII (American Standard Code for Information Interchange) 那么char类型就是依据这个的

    //比如  
    char a = ("a");
    //当我试图: 
    int = a + 1; 
    //结果又是多少呢?
    //答案很简单,编辑器会拿着这个a在ASCII表里面查到对应的10进制进行计算

    很显然字符a对应的十进制就是97 那么此时 int = 97 + 1;

    难道这么大张的ASCII需要我们背下来嘛?  其实不用因为有一个更加便捷的办法只需要我们手写一段代码即可,比如此时我要打印字符A在十进制中表示什么就可以写:

    printf("%d\n",'a'); //97
    printf("%d\n",'A'); //65

    算数运算符小结:

    注意事项:

    /%的区别  ,一个是进行除法/运算,去结果的商,另一个是获取结果的余数%

    整数运算时(+、-、*、/)最终的结果是一个整数,即使有小数也会被抛弃,要想得到小数必须要有小数进行参与计算。

    • 类型一致->直接计算
    • 类型不一致: 默认类型转换>小范围转大范围 ,如果有short和char类型则一律自动提升为int类型
    • 强制转换:大范围转小范围,需要手动写上强制转换的代码,需要强制转换成什么类型就在括号里面写什么类型short  i = (short)b

    相关知识点:

    知识点图片C语言

    C语言基础(第三部分):char、字符串与 scanf 键盘录入详解

    C语言基础入门笔记(第二部分扩展):整数类型、进制与数据存储原理

    C语言基础入门笔记——NO1

    评论

  • 0
    /1000
    最热
  • 最新

    确认跳转

    您即将离开当前页面,访问外部链接。请注意核对网址,保护隐私安全。

    https://example.com

    言心安全助手 · 建议确认来源可信

    • 0
    • 0
    • 1
    登录后参与评论