出自《java puzzle》
下面的程序在计算一个int数组中的元素两两之间的差,将这些差置于一个集合中,然后打印该集合的尺寸大小。那么,这个程序将打印出什么呢?
import java.util.*;
public class Differences {
public static void main(String[ ] args) {
int vals[ ] = { 789, 678, 567, 456, 345, 234, 123, 012 };
Set diffs = new HashSet();
for (int i = 0; i < vals.length; i++)
for (int j = i; j < vals.length; j++)
diffs.add(vals[i] - vals[j]);
System.out.println(diffs.size());
}
}
外层循环迭代数组中的每一个元素,而内层循环从外层循环当前迭代到的元素开始迭代到数组中的最后一个元素。因此,这个嵌套的循环将遍历数组中每一种可能的两两组合。(元素可以与其自身组成一对。)这个嵌套循环中的每一次迭代都计算了一对元素之间的差(总是正的),并将这个差存储到了集合中,集合是可以消除重复元素的。因此,本谜题就带来了一个问题,在由vals数组中的元素结成的对中,有多少唯一的正的差存在呢?
当你仔细观察程序中的数组时,会发现其构成模式非常明显:连续两个元素之间的差总是111。因此,两个元素之间的差是它们在数组之间的偏移量之差的函数。如果两个元素是相同的,那么它们的差就是0;如果两个元素是相邻的,那么它们的差就是111;如果两个元素被另一个元素分割开了,那么它们的差就是222;以此类推。看起来不同的差的数量与元素间不同的距离的数量是相等的,也就是等于数组的尺寸,即8。如果你运行该程序,就会发现它打印的是14。怎么回事呢?
上面的分析有一个小的漏洞。要想了解清楚这个缺陷,我们可以通过将println语句中的.size()这几个字符移除掉,来打印出集合中的内容。这么做会产生下面的输出:
[111,222,446,557,668,113,335,444,779,224,0,333,555,666]
这些数字并非都是111的倍数。在vals数组中肯定有两个毗邻的元素的差是113。如果你观察该数组的声明,不可能很清楚地发现原因所在:
int vals[ ] = { 789, 678, 567, 456, 345, 234, 123, 012 };
但是如果你打印数组的内容,你就会看见下面的内容:
[789,678,567,456,345,234,123,10]
为什么数组中的最后一个元素是10而不是12呢?因为以0开头的整数类型字面常量将被解释成为八进制数值[JLS 3.10.1]。这个隐晦的结构是从C编程语言那里遗留下来东西,C语言产生于1970年代,那时八进制比现在要通用得多。
一旦你知道了012 == 10,就会很清楚为什么该程序打印出了14:有6个不涉及最后一个元素的唯一的非0差,有7个涉及最后一个元素的非0差,还有0,加在一起正好是14个唯一的差。订正该程序的方法更加明显:将八进制整型字面常量012替换为十进制整型字面常量12。如果你这么做了,该程序将打印出我们所期望的8。
本谜题的教训很简单:千万不要在一个整型字面常量的前面加上一个0;这会使它变成一个八进制字面常量。有意识地使用八进制整型字面常量的情况相当少见,你应该对所有的这种特殊用法增加注释。对语言设计者来说,在决定应该包含什么特性时,应该考虑到其限制条件。当有所迟疑时,应该将它剔除在外。
分享到:
相关推荐
PHP计算两个日期相差几个月多余几天
下面重点讨论一下PCB差分信号设计中几个常见的误区
Matlab图像处理的常用几个方法并附有帧差法
差分信号PCB布局布线时有几个常见误区,我们来梳理一下:差分信号PCB布局布线时有几个常见误区,我们来梳理一下......
差分信号PCB布局布线时的几个常见误区认为差分信号不需要地平面作为回流路径,或者认为差分走线彼此为对方提供回流途径。造成这种误区的原因是被表面现象迷惑,或者对高速信号传输的机理认识还不够深入。虽然差分...
35丨技术进阶之道:你和这个星球最顶级的程序员差几个等级?.pdf
网上很多资源都没有输出结果是(相差几年几个月几天的代码)希望对大家有帮助 有不足地方 望大家多多指点
等差数列前+n项和定理的几个推广定理及运用_数学等差数列论文毕业设计范文.pdf
java时间差java时间差java时间差java时间差
用于计算两个时间的差值,非常实用!
java中计算两个日期相差几天 1.public class Test { 2.public void dateDiff(String startTime, String endTime, String format) { 3.//按照传入的格式生成一个simpledateformate对象 4.SimpleDateFormat sd = ...
通过建立一个或几个离散变量取值所满足的平衡关系,从而建立差分方程。 差分方程就是针对要解决的目标,引入系统或过程中的离散变量,根据实际背景的规律、性质、平衡关系,建立离散变量所满足的平衡关系等式,从而...
matlab多射击差分动态规划算法(MS-DDP)在MATLAB中实现,并结合几个机器人实例.zip
七年级数学下册第八章整式的乘法8.4整式的乘法平方差公式应用的几个误区素材新版冀教版
几个有关OpenGL的实例,基于VC++6.0平台...
计算两日期之间的差,看看两日期之间能差几个月的问题
我们从这两张图中能确定几个要点。 首先,在低频率下,共模抑制和共模增益(衰减)都非常有用。 然而,在较高的频率下会怎样呢?CMRR 和共模衰减都开始变差。如果所涉及的系统在极高频率下具有很大的噪声(例如...
这是一个计算日期差,是用JS来写的,可以好好看看用用
差分信号和普通的单端信号走线相比,明显的优势体现在以下三个方面: 1.抗干扰能力强,因为两根差分走线之间的耦合很好,当外界存在噪声干扰时,几乎是同时被耦合到两条线上,而接收端关心的只是两信