00:00
我们现在已经完全了解了skyla里边的类型系统,也已经知道了数据类型之间进行转换的规则,自动类型转换和强制类型转换,那在强制类型转换的这一部分里边呢,前面其实提到了一个要点,就是大家要注意做强转之后有可能会引起精度的缺失,或者数据直接溢出啊,有可能我们整个这个代码的这个逻辑就会发生错误,那这一点大家需要非常的小心,那这里给大家举一个非常经典的面试题的例子,我们来看一看,就可以理解清楚这个东西到底是怎么一回事了。啊大家看这一个代码呢,也非常的简单,这是scla的一个代码写出来的一个面试题啊,代码非常简单,就是我们定义了一个int类型的N这样的一个变量,它的值是130,然后呢,诶,我们把它直接突BY强转,转成了一个低精度的bitt。然后打印这个B,那么这个B的值到底应该是多少呢?哎,我们接下来在代码里边把这个例子也做一个实现。
01:08
我们还是直接去拗一个scalela的object,刚且我们这个叫做TEST09,这算是一个运型转换的一个题目了啊,我们叫problem it type version,那还是把main方法先写出来,这边我们的关键就在于定义一个艾特类型的比例,它是130。然后这里大家看到了啊,就是本身我们应该想要得到个BAT类型的值,如果你直接给130的话,大家知道BAT类型只有一个字节,它表示的范围是负128到正127,所以你给百一百二十七是可以的,那你给128就不行了,对吧?所以你这里直接给一百三没错,所以呢,我们这里就先给一个N,它的值是类型,然后接下来呢,把它做一个强转,转换成bit类型。
02:20
所以这里面就涉及到一个问题,最终得到的这个B,那不应该是多少呢?我们首先想到肯定不可能是一百三了,因为BAT根本就不能表示一百三那么大的数,那现在到底应该得到多少呢?我们可以直接运行一下,先看一看结果。大家看到很奇怪,直接变成了一个负数,变成了一个负126。这又到底是怎么回事呢?这其实涉及到了我们之前给大家解释过的,按照字节保存数据的时候,我们保存。有符号数据与呃,它主要在底层是一个补码的表示,主要跟它的这个补码表达有关系,而我们在做这个强转的时候呢,它其实非常简单粗暴的去直接截取,比方说我们tobe。
03:16
Int本身有四个字节,Tobe的时候呢,就是直接简单粗暴的去截取了它的最后一个字节,那当然大家也知道了,如果前面是涉及到这个精度缺失的话啊,那前面可能就缺了一部分数据,那如果说这里边是涉及到你连那个符号位都变化的话,那当然就会直接发生这样的一个错误了,对吧?哎,数据相当于直接溢出了。啊,那接下来我们就来看一下怎么样去解释这个问题,那想要解释这个130,我们先来给大家讲一个比较简单的例子,是128 128大家知道本身这也是能表示的一个数据,对吧?哎,那128我们在上面直接给大家完整的把这个。
04:02
分析的过程写出来,首先我们要写一下128。Int类型,那么在计算机底层要占据四个字节32位,所以大家会想到这个正128计算机里边本身应该是什么样的一个数呢?128本身是二的七次方嘛,那其实应该是一后边这个零,诶大家知道它其实本身就占八位对吧,如果说你要用一个int类型32位来表示的话,那是不是前面都要补零啊,所以它本身的这个。是啊,我们把这个补出来,前面都是零,所以它应该是32位,前面呃,大家看到这应该是24位都是零,后边是一个一,然后再跟七个零,这就是它的码表示,那自然了,对应的这个补码表示又是什么呢?本身是一个正数。
05:15
负数的话,首位是零嘛,后边是不是完全不变啊,原码是什么样,补码还是什么样,所以说这个并没有任何的区别,那现在接下来下来我们要截取背后一个字节,那么接下来这个截取最后一个字节转换成这个BY对吧,做这个强转,那这里我们截取的不然就只有10000000啊,那大家看一下这个10000000。得到的是得到的,本来这应该是一个补码的表达,对吧,大家回忆一下这个补码一个字节的BAT,这个补码10000000表示的原始的数到底应该是什么呢?
06:08
因为我们发现了当前的这一个幺,它其实表示的是符号位,所以这是一个负数,而负数当前如果要是取它的这个源码的话,那应该是,哎,大家知道这个取反加一对吧,取反之后是全部都是幺,幺在加一之后,诶,进位又变成了10000000,那这个时候我们其实用它是表示我们不是表示负零,我们表示的是最大的负数对吧?这里我们表示最大的负数其实是负128,所以如果我们直接把128TO By做强转的话,得到的这个B应该是负128。那现在如果说我们把它转换成一百三的话,那应该是一个什么样子呢?的过程其实非常的类似分析的流程,我们把它换成130,那int类型的话还是占据四个字节32位,只不过这里它比128多了二,那当然128是10000000,它多二当然就是10001010了,它的补码呢当然也还不变,那最后这里边截取出来的最后一个字节八位也是10000010。
07:28
那这个数到底表示的是又是什么呢?呃,其实大家知道在这个补码表达里边,它不就是完全把这个正负数统一起来了吗?之前10000000表示的是负128,那再加一再加二变成0010是不是就是负128加二就应该是负126啊啊,当然我们也可以具体做一个分析,因为现在已经不涉及到负128这个最大负数的别定义了,那我们看一下对应的源码应该又是什么?
08:02
啊,那对应源码的话,知道同样还是取反加一就可以得到它的这个对应源码,那如果要是取反的话,二倍不变还是负的,后边是111。1101加一,那是不是1110啊啊,那所以后边这个数又是多少呢?这个数当然就是。如果全是幺,那是127嘛,所以现在当然就是126,所以它就是负126。啊,这就是我们关于一道面试题目的一个解释啊,做强制类型转换之后,正数变负数,它的范围溢出了正数变负数。一百三得到的是负126啊,所以大家其实就会发现了,128得到的是负128,那130比128大二,那么得到的这个转换之后的数呢,也是溢出之后也是要比负128大二,那同样我们就知道,如果要是一百一百三十三呢。
09:04
那是不是在这个基础上加三啊。大家基础上再加三,那就应该是负123对吧?哎,所以其实就是这样的一个非常简单的一个规律,大家可以把这道面试题好好再总结一下,涉及到强制类型转换的精度缺失和数据溢出的问题。
我来说两句