《java解惑》笔记一

本文通过四个具体的Java编程实例探讨了奇数判断、浮点运算误差、整数溢出及长整数表示的问题,并深入分析了背后的技术原理。

第一题:奇数性

isOdd方法用来确定传来的参数是否是奇数,由于当传入负数i时,i%2的值为-1或0,负奇数也不能判断正确。由于偶数是对2取余为0,所以应该将i%2==1修改为i%2!=0。修改后,奇数对2取余不是正1或负1都能满足。

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

第二题:找零时刻

public static void main(String[] args) {
        double result= 2.00 - 1.10;
        System.out.println(result);
        System.out.println("2.00双精度在内存表示(16进制):"+ChapterUtil.getIEE754FromDouble(2.00));
        System.out.println("1.10双精度在内存表示(16进制):"+ChapterUtil.getIEE754FromDouble(1.10));
        System.out.println("2.00-1.10结果双精度在内存表示(16进制):"+ChapterUtil.getIEE754FromDouble(result));
        System.out.println("0.90双精度在内存表示(16进制):"+ChapterUtil.getIEE754FromDouble(0.9));
    }
//控制台输出:
//0.8999999999999999
//2.00双精度在内存表示(16进制):4000000000000000
//1.10双精度在内存表示(16进制):3ff199999999999a
//2.00-1.10结果双精度在内存表示(16进制):3feccccccccccccc
//0.90双精度在内存表示(16进制):3feccccccccccccd

ChapterUtils是一个查看数字在内存存储的工具类

public class ChapterUtil {
    public static String getIEE754FromFloat(float i) {
        return Integer.toHexString(Float.floatToRawIntBits(i));
    }
    public static String getFromInt(int i) {
        return Integer.toHexString(i);
    }
    public static String getFromLong(long i) {
        return Long.toHexString(i);
    }
    public static String getIEE754FromDouble(double i) {
        return Long.toHexString(Double.doubleToRawLongBits(i));
    }
}

2.0-1.1 涉及浮点数加减法
在我的一篇博客中介绍了float在内存存储方式,其实double也差不多

double 符号位1位,指数位11位,尾数52位

2.0是正数,符号位0,2的二进制表示为 121 1 ∗ 2 1 ,指数是1,所以指数位为1+1023= 1024(10)=400(16) 1024 ( 10 ) = 400 ( 16 ) ,所以符号位包括指数位就是 400(16) 400 ( 16 ) ,其余由于指数位不全为0,所以是规格的,尾数省去1,都是0.

1.1是正数,符号位0, 1.1的二进制表示为 1.000110011001120 1.000110011 ⋯ ⏟ 以 0011 循 环 ∗ 2 0 ,由于double尾数只能存52位,所以尾数就是 1119a(16) 1 ⋯ ⏟ 11 个 9 a ( 16 ) ,最后一位为a,是因为最后一个9后面还是1,所以进一位由9变为a。指数为0,指数位就是0+1023= 1023(10)=3ff(16) 1023 ( 10 ) = 3 f f ( 16 ) .

浮点数的减法,先对阶,1.1的指数也就是阶码比2少1,尾数向右移一位,隐藏的那一位也右移,得到 811cd(16) 8 ⋯ ⏟ 11 个 c d ( 16 ) ,然后计算尾数的减法,得到 7123 7 ⋯ ⏟ 12 个 3 ,进行规范化操作,因为不满足规范化,向左移2位,最后补0,阶码减2,最后尾数为 13c ⋯ ⏟ 13 个 c ,指数位为-1,所以指数位和符号位一起就是 3fe(16) 3 f e ( 16 ) .最终结果为 3fe13c 3 f e ⋯ ⏟ 13 个 c .

第三题:长整除

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;
        final long MICROS_PER_DAY_LATER = 24L * 60 * 60 * 1000 * 1000;

        System.out.println("一天中微秒数:溢出后的数"+MICROS_PER_DAY);
        System.out.println("一天中微秒数:正确的值"+MICROS_PER_DAY_LATER);
        System.out.println("正确的long在内存存储为:"+ChapterUtil.getFromLong(MICROS_PER_DAY_LATER));
        System.out.println("溢出后的值在内存存储为:"+ChapterUtil.getFromLong(MICROS_PER_DAY));
        System.out.println(MILLIS_PER_DAY);
        System.out.println(MICROS_PER_DAY/MILLIS_PER_DAY);
    }
//控制台输出:
//一天中微秒数:溢出后的数500654080
//一天中微秒数:正确的值86400000000
//正确的long在内存存储为:141dd76000
//溢出后的值在内存存储为:1dd76000
//86400000
//5

由于int与int相乘只会保存在int里,由于最终的结果已经超出int的范围,即使保存在long里,也只是溢出后的值。因为由内存存储可见,舍去了8位,14是十六进制的。

第四题:初级问题

public static void main(String[] args) {
        System.out.println(12345+5432l);
    }
//控制台打印:
//17777

由于5432l中l很像1,特别容易看错,所以一定要用大写的L来表示一个长整数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

aabond

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值