java_puzzlers---表达式之谜(一)

1、奇数性

下面的方法的目的是确定其唯一的参数是否为奇数,这个方法可行吗?

public class Oddity {	
	public static boolean isOdd(int i) {
		return i % 2 == 1;
	}

	public static void main(String[] args) {
	}	
}

其实这个方法不可行的。因为他对于所有的负数的判断都是不正确的,,任何负数调用该方法的结果都为false,解决这个问题可以用下面这种方法:

public class Oddity {
public static boolean isOdd(int i) {
return i % 2 != 0;
}


public static void main(String[] args) {
}
}

这个代码可以进步一步优化为:

public class Oddity {
public static boolean isOdd(int i) {
return (i & 1) != 0;
}


public static void main(String[] args) {
}
}




2、找零时刻

       Tom在一家汽车配件商店购买一个价值1.10美元的火花塞,但是他钱包中都是两美元一张的钞票、如果他用一张两美元的钞票购买这个火花塞,那么应该找给他多少零钱?

       下面是一个试图解决上述问题的程序,它会打印什么呢?

public class Change {
    public static void main(String args[]) {
        System.out.println(2.00 - 1.10);
    }
}


       或许是觉得应该打印的是0.90或者0.9吧,但是很遗憾地告诉你,这是错的。问题在于并不是所有的小数都可以用二进制浮点数精确表示。下面这段代码虽然能够打印正确答案,但它并不是对底层问题的通用解决方法:

public class Change {
    public static void main(String args[]) {
        System.out.printf("%.2f\n",(2.00 - 1.10));
    }
}

      其实,二进制浮点对于货币计算是非常不适合的。对于这个问题我们有两种解决方案。第一,以分为单位表示货币值后重写prinfln语句,这个版本将打印正确答案90美分:

public class Change {
public static void main(String args[]) {
System.out.println((200 - 110) + "cents");
}
}

另一种解决方案是使用执行精确小数运算的 BigDecimal。这里注意一点:一定要用BigDecimal(String)构造器,而千万不要用BigDemal(double)。程序如下:

public class Change {
public static void main(String args[]) {
System.out.println(new BigDecimal("2.00").subtract(new BigDecimal("1.10")));
}
}

   总之,在需要精确答案的地方,要避免是使用float和double;对于货币计算,要使用和int、long或BigDecimal。


3、长整数

       这个谜题被称为长整数,因为它所涉及的程序是整除两个long型的整数值的。被除数表示一天里的微妙数,而除数表示一天里的毫秒数。这个程序会打印什么呢?

public class LongDivision {
    public static void main(String[] args) {
        final long MICROS_PER_DAY = 24 * 60 * 60 * 1000 * 1000;
        final long MILLIS_PER_DAY = 24 * 60 * 60 * 1000;

        System.out.println(MICROS_PER_DAY / MILLIS_PER_DAY);
    }
}



      或许你也会和我一样地认为会打印1000吧,但是还是很遗憾地告诉你,我们都错了,这个程序打印的是5。因为这个计算完全是以int运算来执行的,并且只有在运算完成之后,其结果才被提升到long,但是此时已经太迟了,计算已经溢出,它返回的是一个1/200倍的数值。

       Java不具有目标确定类型的特征,这是一种语言特征,其含义是指存储结果的变量类型会影响计算所使用的类型。我们可以将后续计算都用long运算来完成,程序如下:

public class LongDivision {
public static void main(String[] args) {
final long MICROS_PER_DAY = 24L * 60 * 60 * 1000 * 1000;
final long MILLIS_PER_DAY = 24L * 60 * 60 * 1000;


System.out.println(MICROS_PER_DAY / MILLIS_PER_DAY);
}
}

       这道题目给我们的教训是:当你在操作很大的数字时,千万要提放溢出---它可是一个缄默杀手。



4、初级问题 

      前面那个谜题有点棘手,但它是有关整除的,每个人都知道整除是很麻烦的。下面的程序只设计加法,它又会打印什么呢?

public class Elementary {
    public static void main(String[] args) {
        System.out.println(12345 + 5432l);
    }
}



       从表面上看这是一个简单的问题,简单到你只要口算就可以知道答案是666666了。但是当你运行这个程序的时候你发现结果并不是你想象中的那个数字。这一切到底是为什么呢?

      这个时候你或许应该睁大眼睛看看源程序,你有没有注意到加号后面那个数的最后一位不是数字1而是小写字母l。所以正确答案是17777,。这时候你可能在大喊着“恶心”。但是至少你就应该明白这样一个教训:在long类型字面常量中,一定要用大写字母L,千万不要用小写的l。类似地,要避免使用单个小写字母l作为变量名。






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
********Shenkxiao Resources******** 压缩包密码:shenkxiao 资源:Java解惑(中文版)、java puzzlers traps pitfalls,and Corner Cases 作者:Joshua Bloch Neal Gafter 版本:中文版 主要内容: Java解惑(英文版)—典藏原版书苑 目录 1 introduction 2 expressive puzzlers puzzle 1:oddity puzzle 2:time for a change puzzle 3:long pision puzzle 4:it s elementary puzzle 5:the joy of hex puzzle 6:multicast puzzle 7:swap meat puzzle 8:dos equis puzzle 9:tweedildum puzzle 10:tweedledee 3 przzlers with character puzzle 11:the last laugh puzzle 12:abc puzzle 13:animal farm puzzle 14:escape rout puzzle 15:hello whirled puzzle 16:line printer puzzle 17:huh? puzzle 18:string cheese puzzle 19:classy fire puzzle 20:what s my class? puzzle 21:what s my class,take2 puzzle 22:dupe of url puzzle 23:no pain,no gain 4 loopy puzzlers puzzle 24:a big delight in every byte puzzle 25:inclement increment puzzle 26:in the loop puzzle 27:shifty i s puzzle 28:looper puzzle 29:bride of loper puzzle 30:son of loper puzzle 31:ghost of looper puzzle 32:curse of looper puzzle 33:looer meets the wolfman puzzle 34:down for the count puzzle 35:minute by minute 5 exceptonal puzzlers 6 classy puzzlers 7 library puzzlers 8 classier puzzlers 9 more library puzzlers 10 advanced puzzlers a catalog of traps and pitfalls b notes on the illusions refereces index 本书深入研究Java编程语言及其核心类为的细微之处,特写95个有关Java或其他类库的陷阱和缺陷的谜题,其中大多数谜题都采用短程序的形式给出。在每个谜题之后都有详细的解惑方案,这些方案在给出那些实际行为与表面上迥异的程序行为的简单解释的同时,更向读者展示了如何一劳永逸地避免底层的陷阱与缺陷。本书附录部分列出了陷阱及缺陷的目录,可供读者进一学习参考。 本书以轻松诙谐的语言,寓教于乐的方式,由浅入深、总结归纳Java编程语言的知识点,适合具有Java知识的学习者和有编程经验的Java程序员阅读。 上传理由:精品典藏共享,网络上下载该资源太费劲,我来共享吧 因为是精品所以分数也比较高。 ***********************************

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值