`
yangshen998
  • 浏览: 1250192 次
文章分类
社区版块
存档分类
最新评论

长整除谜题

 
阅读更多
这个谜题之所以被称为长整除是因为它所涉及的程序是有关两个long型数值整除的。被除数表示的是一天里的微秒数;而除数表示的是一天里的毫秒数。这个程序会打印出什么呢?

这个谜题看起来相当直观。每天的毫秒数和每天的微秒数都是常量。为清楚起见,它们都被表示成积的形式。每天的微秒数是(24小时/天*60分钟/小时*60秒/分钟*1000毫秒/秒*1000微秒/毫秒)。而每天的毫秒数的不同之处只是少了最后一个因子1000。

当你用每天的毫秒数来整除每天的微秒数时,除数中所有的因子都被约掉了,只剩下1000,这正是每毫秒包含的微秒数。

除数和被除数都是long类型的,long类型大到了可以很容易地保存这两个乘积而不产生溢出。因此,看起来程序打印的必定是1000。

遗憾的是,它打印的是5。这里到底发生了什么呢?

问题在于常数MICROS_PER_DAY的计算“确实”溢出了。尽管计算的结果适合放入long中,并且其空间还有富余,但是这个结果并不适合放入int中。这个计算完全是以int运算来执行的,并且只有在运算完成之后,其结果才被提升到long,而此时已经太迟了:计算已经溢出了,它返回的是一个小了200倍的数值。从int提升到long是一种拓宽原始类型转换(widening primitive conversion),它保留了(不正确的)数值。这个值之后被MILLIS_PER_DAY整除,而MILLIS_PER_DAY的计算是正确的,因为它适合int运算。这样整除的结果就得到了5。

那么为什么计算会是以int运算来执行的呢?因为所有乘在一起的因子都是int数值。当你将两个int数值相乘时,你将得到另一个int数值。Java不具有目标确定类型的特性,这是一种语言特性,其含义是指存储结果的变量的类型会影响到计算所使用的类型。

通过使用long常量来替代int常量作为每一个乘积的第一个因子,我们就可以很容易地订正这个程序。这样做可以强制表达式中所有的后续计算都用long运作来完成。尽管这么做只在MICROS_PER_DAY表达式中是必需的,但是在两个乘积中都这么做是一种很好的方式。相似地,使用long作为乘积的“第一个”数值也并不总是必需的,但是这么做也是一种很好的形式。在两个计算中都以long数值开始可以很清楚地表明它们都不会溢出。下面的程序将打印出我们所期望的1000:


这个教训很简单:当你在操作很大的数字时,千万要提防溢出——它可是一个缄默杀手。即使用来保存结果的变量已显得足够大,也并不意味着要产生结果的计算具有正确的类型。当你拿不准时,就使用long运算来执行整个计算。

语言设计者从中可以吸取的教训是:也许降低缄默溢出产生的可能性确实是值得做的一件事。这可以通过对不会产生缄默溢出的运算提供支持来实现。程序可以抛出一个异常而不是直接溢出,就像Ada所作的那样,或者它们可以在需要的时候自动地切换到一个更大的内部表示上以防止溢出,就像Lisp所作的那样。这两种方式都可能会遭受与其相关的性能方面的损失。降低缄默溢出的另一种方式是支持目标确定类型,但是这么做会显著地增加类型系统的复杂度

分享到:
评论

相关推荐

    Java谜题Java谜题1——表达式谜题

    谜题3:长整除 谜题4:初级问题 谜题5:十六进制的趣事 谜题6:多重转型 谜题7:互换内容 谜题8:Dos Equis 谜题9:半斤 谜题10:八两 Java谜题2——字符谜题 谜题11:最后的笑声 谜题12:ABC 谜题13:...

    java解惑 书pdf精简版

    谜题3:长整除 谜题4:初级问题 谜题5:十六进制的趣事 谜题6:多重转型 谜题7:互换内容 谜题8:Dos Equis 谜题9:半斤 谜题10:八两 第3章 字符之谜 谜题1l:最后的笑声 谜题12:ABC 谜题13:动物庄园 谜题14:...

    Java解惑(谜题)CHM中英文双版本

    谜题3:长整除 谜题4:初级问题 谜题5:十六进制的趣事 谜题6:多重转型 谜题7:互换内容 谜题8:Dos Equis 谜题9:半斤 谜题10:八两 Java谜题2——字符谜题 谜题11:最后的笑声 谜题12:ABC 谜题13:...

    java 谜题95

    Java谜题1——表达式谜题 3 谜题1:奇数性 3 谜题2:找零时刻 4 谜题3:长整除 6 谜题4:初级问题 7 谜题5:十六进制的趣事 8 谜题6:多重转型 10 谜题7:互换内容 11 谜题8:Dos Equis 13...

    Java 谜题解惑

    Java 谜题解惑。如:奇数性、找零时刻、长整除、十六进制等相关疑惑。

    Java解惑[高清].pdf

    谜题3:长整除 9 谜题4:初级问题 11 谜题5:十六进制的趣事 13 谜题6:多重转型 15 谜题7:互换内容 17 谜题8:Dos Equis 19 谜题9:半斤 21 谜题10:八两 23 第3 章字符之谜 25 谜题11:最后的笑声 25 ...

    Java谜题.txt

    谜题1:奇数性 下面的方法意图确定它那唯一的参数是否是一个奇数。这个方法能够正确运转吗? public static boolean isOdd(int i){ return i % 2 == 1; } 奇数可以被定义为被2整除余数为1的整数。...

    python少儿编程基础课趣解数字谜题.pptx

    数学运算 除法: / 整除: // 求余: % print(31/3)print(31//3)print(31%3) 运行结果: 10.333333333333334 10 1 python少儿编程基础课趣解数字谜题全文共19页,当前为第4页。 龙腾数 如果数字各个位数之和等

    Java谜题解惑 中文版CHM格式

    Java谜题1——表达式谜题 谜题1:奇数性 下面的方法意图确定它那唯一的参数是否是一个奇数。这个方法能够正确运转吗? public static boolean isOdd(int i){ return i % 2 == 1; } 奇数可以被定义为被2整除余数为...

    Java Puzzlers 中文版(Java解惑)

    Java 谜题 1——表达式谜题 谜题 1:奇数性 下面的方法意图确定它那唯一的参数是否是一个奇数。这个方法能够正确运转 吗? public static boolean isOdd(int i){ return i % 2 == 1; } 奇数可以被定义为被 2 整除余数...

    abap-puzzles:ABAP中的编程难题和解决方案

    谜题 编程难题和挑战,ABAP中的示例解决方案 我的目的是演示使用ABAP语言的许多方面来解决ABAP中这些难题和挑战的不同方法,同时给出一些有关如何解决ABAP中实际问题的想法。 :) 希望我能够阐明ABAP方法的一些异同...

Global site tag (gtag.js) - Google Analytics