两个整数相除,计算结果里的小数会直接舍弃。如果将 double 变量赋值给 int,同样有可能丢失精度。出现这类意料之外的运算结果,根源大多在于数据类型转换。我们先理清隐式转换自动触发的场景,再讲解强制转换的写法,以及如何规避精度丢失问题。

什么是类型转换

类型转换(Type Casting)允许把一种数据类型转换成另一种。C 语言里用强制转换运算符 (type)value 做显式转换:

(type)value;

整型除法会截断小数部分,这是初学者最容易出错的地方。看两个对比:

int f = 9 / 4;
printf("f : %d\n", f);      // 输出: 2(小数被截断)

先把 9 转成 float 再做除法,结果就带小数了:

float f = (float) 9 / 4;
printf("f : %f\n", f);      // 输出: 2.250000

显式转换(强制类型转换)示例

#include <stdio.h>

int main() {
    float f = (float) 9 / 4;
    printf("f : %f\n", f);
    return 0;
}

输出:

f : 2.250000

这里的 (float) 把 9 从 int 转成 float,除法就变成浮点除法,结果是 2.25 而不是 2。

隐式转换(自动发生)

有些转换不用你写,编译器自动处理:

  • 赋值时窄类型 → 宽类型:int 赋给 float、float 赋给 double,自动提升。
  • 混合运算时小类型被提升:int 和 float 相加,int 先转成 float 再算。
  • 整数除法:两个 int 相除结果还是 int,小数直接丢掉(不是四舍五入)。
int a = 5, b = 2;
double d = a / b;      // 先算 5/2=2(int),再给 double,结果是 2.0 不是 2.5
double d2 = (double)a / b;  // 强制转换后才是 2.5

数据丢失:为什么建议从低转高

把值从宽类型转成窄类型可能丢精度或溢出:

double pi = 3.14159;
int n = (int)pi;       // n 变成 3,小数部分丢了

int big = 100000;
char c = (char)big;    // char 太小,发生截断,结果不是 100000

经验法则就一句:转方向尽量从窄到宽,别反过来(int → float → double → long double,越往后越宽);从宽往窄转,丢精度甚至溢出,要格外小心。

高 → 低:可能丢精度 / 溢出,要小心 long double 8 字节 double 8 字节 float 4 字节 int 4 字节 低 → 高:转过去一般安全
类型从窄到宽,转过去一般安全;从宽往窄转,可能丢精度或溢出。

典型场景

  • 除法要小数(float) a / ba / (double) b
  • 数学函数参数:有些函数要求特定类型,传错类型时显式转换。
  • 指针转换:void 指针读值时要转回原类型(见 void 指针一章)。

要小数,就把除法里至少一个操作数显式转成浮点;从窄类型往宽类型转很安全,反过来转就得留意精度和溢出。