TA的每日心情 | 开心 2021-3-12 23:18 |
---|
签到天数: 2 天 [LV.1]初来乍到
|
一、案例编号:
U02C05
二、案例名称:
你知道什么是缄默溢出吗?
三、关键词:
缄默溢出
四、案例情景描述:
我们来做这么一件事情:我们求一下一天当中有多少纳秒(ns)。这个问题逻辑上很简单,我想这段代码你肯定是信手拈来。
/*
*一天24小时,每小时60分钟,每分钟60秒,每秒1000毫秒,每毫秒1000纳秒
*/
long micro_seconds_per_day=1*24*60*60*1000*1000;
System.out.println(micro_seconds_per_day);
但是当你运行这段代码看到输出结果的时候肯定会大吃一惊。它结果是:500654080。单单从最低位0的个数看,我们就知道这个结果肯定是错误的。
奇怪!为什么会错!逻辑没有问题,计算机对于这种简单的乘法运算也不应当出错。而且这段代码无论你运行多少次都是这个结果,看来不会是计算机的问题。
五、案例理论分析:
罪魁祸首就是这一行代码:long micro_seconds_per_day=1*24*60*60*1000*1000;
我们来分析一下它:
整型的字面值默认为int类型。上述代码在运算的时候是进行的int类型的运算,运算过程中产生的一切中间结果都要保存在int类型的空间中。运算结束后再把运算结果转换成long类型并赋值给变量micro_seconds_per_day。
这个表达式1*24*60*60*1000*1000的运算结果用8个byte的二进制数来表示是:
00000000,00000000,00000000,00010100,00011101,11010111,01100000,00000000。
对于4个byte的int类型而言肯定是溢出了,因此要进行类型缩窄转换。类型缩窄砍掉了高位的4个字节变成
00011101,11010111,01100000,00000000,
转换成十进制就是500654080。而这次类型缩窄转换完全是程序在运行过程中自动完成的,程序员是毫不知情的。因此,才会出现令人瞠目结舌的结果。对于这种现象我们就称之为“缄默溢出”。造成“缄默溢出”的本质原因不是程序员的问题,而是语言设计者的问题。但是作为程序员在语言的应用过程中,要规避这种现象。那如何规避呢?很简单只要让表达式不进行int类型的运算,而进行long类型的运算即可。修改很简单:
long micro_seconds_per_day=1*24*60*60*1000*1000L; |
|