类型转换就是把一种类型的数据,变成另一种类型。

上位机里这种需求天天有:PLC 读上来的原始值常常是 int,换算工程量要用 double,算完又要显示成文字给操作员看。这一路就得不断做类型转换。这篇就讲两种转换:自动转换和强制转换。

本篇目标:分清「自动转换」和「强制转换」什么时候发生、会不会丢数据,能自己写转换代码,知道两个最容易踩的坑。


一、先打个比方:大杯子和杯子

记住这个比喻,整篇都靠它。

想象两个杯子:

  • 小杯子倒进 大杯子:水不会洒,安全,随便倒。
  • 大杯子倒进 小杯子:水会溢出来,你得自己小心,还可能洒掉。

类型转换一模一样。范围小的类型(比如 byte)转成范围大的类型(比如 int),就像小杯子倒大杯子,安全;反过来范围大的转范围小的,就像大杯子倒小杯子,可能丢数据。


二、自动转换(隐式转换)

自动转换就是「小转大」,电脑自动帮你完成,不用写任何东西,也不会丢数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
using System;

class Program
{
static void Main()
{
byte b = 100; // 小:byte
int i = b; // 自动转成 int,不用写任何东西
long l = i; // int 自动转 long
double d = i; // int 自动转 double(整数转小数,安全)

Console.WriteLine(b); // 100
Console.WriteLine(i); // 100
Console.WriteLine(l); // 100
Console.WriteLine(d); // 100
}
}

上面的代码直接就能跑,没有报错。因为 byte 的范围完全装得进 int,int 装得进 long,int 也能无损转成 double。电脑一看「这是安全的」,就自动帮你转了。

自动转换的方向是「小到大、整数到小数」。判断标准就一条:目标类型能不能完整装下原来的值。装得下就自动转。


三、强制转换(显式转换)

强制转换就是「大转小」,电脑不帮你,必须你自己写代码,而且可能丢数据。

强制转换的写法:在值前面加括号和类型。

1
2
3
4
5
6
7
8
9
10
11
12
13
using System;

class Program
{
static void Main()
{
double d = 25.6;
int i = (int)d; // 强制转 int,小数部分直接砍掉

Console.WriteLine(d); // 25.6
Console.WriteLine(i); // 25
}
}
看清楚:小数是怎么丢的

25.6 转成 int 后变成了 25,小数点后的 0.6 被直接砍掉了,不是四舍五入。这就是「强制转换会丢数据」的意思——大杯子倒小杯子,水洒出来一部分。

强制转换的语法是 (目标类型)值,比如 (int)d。括号里写你想转成的类型。


四、一张表记住谁能自动转

自动转换有个固定方向,从范围小的一直往范围大的走。下面这张表从下往上,就是自动转换的方向。

类型 范围
double 最大,带小数
float 带小数,比 double 小
long 大整数
int 整数
short 小整数
byte 最小整数

记两个关键结论:

  • 整数之间,范围小的能自动转范围大的:byte 到 short、int、long。
  • 整数能自动转浮点:int 可以自动转 float、double。
  • 反过来,double 转 int、long 转 int,都必须强制转换,还可能丢数据。
完整对照:哪些能自动转
能不能自动
byteint
intlong
intdouble
shortint
doubleint不能,要强制
longint不能,要强制
floatdouble
doublefloat不能,要强制

一句话:小的能自动变大的大的变小的必须强制


五、强制转换的两个坑

强制转换最怕两件事:丢小数、溢出。下面分别看。

坑一:丢小数

1
2
3
4
5
6
7
8
9
10
11
12
using System;

class Program
{
static void Main()
{
double temp = 36.9;
int t = (int)temp; // 变成 36,0.9 没了

Console.WriteLine(t); // 36
}
}

36.9 转成 int 变成 36,小数被砍掉,不是四舍五入。上位机里温度、压力这种数据如果随便强制转 int,精度就丢了。

坑二:溢出

1
2
3
4
5
6
7
8
9
10
11
12
using System;

class Program
{
static void Main()
{
long big = 300; // long 装 300 没问题
byte small = (byte)big; // 强制转 byte,但 byte 最大只能到 255

Console.WriteLine(small); // 44,不是 300!
}
}

300 转成 byte 后变成了 44,因为 byte 只能装 0 到 255,300 超了,数字被「绕」回去了。这就是溢出。所以大转小之前,一定要想清楚目标类型能不能装下。

为什么 300 会变成 44

byte 只有 8 位,最大装 255。300 比 255 大了 45,多出来的部分从 0 开始重新数,就得到了 44。这个「绕圈」现象叫溢出,新手很容易踩,务必记住:大转小,先想清楚装不装得下。


六、上位机实战:模拟量换算里的转换

把转换串进之前学的模拟量换算。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
using System;

class Program
{
static void Main()
{
// 1) PLC 读上来的原始值,是 int
int raw = 13824;

// 2) 自动转换:int 和 double 一起算,int 自动转成 double
// 结果 real 是 double,不会丢小数
double real = raw / 27648.0 * 100.0;
Console.WriteLine("实际温度:" + real); // 实际温度:50

// 3) 强制转换:界面有时只要整数,就转回 int
int display = (int)real;
Console.WriteLine("显示温度:" + display); // 显示温度:50
}
}
拆解这段代码的转换过程
  • 第 2 步 raw / 27648.0 * 100.0:raw 是 int,27648.0 是 double。int 和 double 混合运算时,int 自动转成 double,结果就是 double。这是自动转换。
  • 第 3 步 (int)real:real 是 double,要变回 int 显示,必须强制转换。这里 50 没有小数,所以没丢数据。

实际温度 50 正好是整数,但如果算出来是 50.5,强制转 int 就会变成 50,小数就丢了。要不要保留小数,取决于你的显示需求。


七、小结

这一篇我们搞懂了两种类型转换:

  • 自动转换(隐式):小转大、整数转小数,电脑自动完成,安全不丢数据。
  • 强制转换(显式):大转小,必须自己写(类型)值,可能丢小数、可能溢出。

口诀:

小转大,自动跑;大转小,要强制,当心丢数和溢出。

能说出自动转换是「小转大、安全」

会写(int)这种强制转换

知道 double 转 int 会丢小数

知道大整数转小整数可能溢出


八、能跑起来的小练习

点我看完整练习代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
using System;

class Program
{
static void Main()
{
// 1) 自动转换:小转大
byte b = 200;
int i = b;
double d = i;
Console.WriteLine(i); // 200
Console.WriteLine(d); // 200

// 2) 强制转换:大转小,丢小数
double temp = 25.7;
int t = (int)temp;
Console.WriteLine(t); // 25

// 3) 自动转换:int 和 double 混合运算
int raw = 13824;
double real = raw / 27648.0 * 100.0;
Console.WriteLine(real); // 50
}
}