妈,旧电脑连加法都算错了,我要换新的

简介: 妈,旧电脑连加法都算错了,我要换新的

妈妈,我的电脑连加法都算错了

垃圾电脑,连一个加法都算不对

小朱: 怎么给儿子换电脑了,我那旧电脑她不想嘛。
小仙女: 你也知道旧电脑,连个加法都算不对,你好意思。
小朱: 纳尼,什么加法算不对。

示例

public static void main(String[] args) {
    float f = 2000000000f;
    System.out.println((f + 50f) == f);
}
AI 代码解读

小仙女: 虽然我没学过,但是没吃过猪肉,没见过猪跑吗?肯定是false啊。但是得到的竟然是true
小朱: 😯,那你新电脑试过了吗?
小仙女: 那还用试吗,肯定没问题,我试下好了。
......
小仙女: 走,和我一起找他们理论去,垃圾电脑,毁我儿子。
小朱: ......

各位,你们的电脑是不是也出问题了。😄😄😄

解析

我们先来了解计算机怎么存储float的数据
float的存储正是将4字节32位划分为了3部分来分别存储正负号,指数部分,小数部分

  • 1.Sign(1位): 用来表示浮点数是正数还是负数,0表示正数,1表示负数。
  • 2.Exponent(8位): 指数部分。为了同时表示正负指数以及他们的大小顺序,这里实际存储的是指数+127。
  • 3.Mantissa(23位): 尾数部分。

我们先算2000000000f的二进制

float f =  2000000000f;
int i = Float.floatToIntBits(f);
System.out.println(Integer.toBinaryString(i));
//运行结果
//1001110111011100110101100101000
AI 代码解读

结果应该在补一个0,正好32位。
有同学有可能对着很模糊,为什么2000000000f这的二进制是这样的。下面我们来介绍一下,因为这个例子全是整数部分所以这么写

public static void main(String[] args) {
    Integer x = 2000000000;
    StringBuilder stringBuilder = new StringBuilder();
    while (x >= 1){
        //求余数
        Integer y = x % 2;
        x = x / 2;
        stringBuilder.append(y);
    }
    //反转字符串
    stringBuilder.reverse();
    System.out.println(stringBuilder);
}
//结果
//1110111001101011001010000000000
AI 代码解读

1110111001101011001010000000000可以写成1.11011100110101100101 * 2^30

第一步: Sign(1位)因为是正数所以第一位是0
第二步: Exponent(8位)因为指数是30+127=157转成二进制是10011101
第三步: Mantissa(23位)11011100110101100101,000这个地方不足23位补0,以逗号分割
综上所得第一步➕第二步➕第三步不足32位补0得到
0,10011101,11011100110101100101,000,这就得到上面的值了(上面的值第一位0隐藏了)。
到这里读者还是不明白为什么(f + 50f) == ftrue,其实2000000000f == 2000000050f。是不是不可思议。当你把2000000050f用二进制表示出来你就知道了。

float f =  2000000050f;
int i = Float.floatToIntBits(f);
System.out.println(Integer.toBinaryString(i));
//运行结果
//1001110111011100110101100101000
AI 代码解读

没有任何变化,为什么呢?我们来按我们的方法去写。

public static void main(String[] args) {
    Integer x = 2000000050;
    StringBuilder stringBuilder = new StringBuilder();
    while (x >= 1){
        //求余数
        Integer y = x % 2;
        x = x / 2;
        stringBuilder.append(y);
    }
    //反转字符串
    stringBuilder.reverse();
    System.out.println(stringBuilder);
}
//结果
//1110111001101011001010000110010
AI 代码解读

同上面
1110111001101011001010000110010可以写成1.11011100110101100101000011001 * 2^30

第一步: Sign(1位)因为是正数所以第一位是0
第二步: Exponent(8位)因为指数是30+127=157转成二进制是10011101
第三步: Mantissa(23位)11011100110101100101000,011001因为超了23位,所以多余的部分是四舍五入,这里是遇1进位所以得到的是11011100110101100101000
综上所得第一步➕第二步➕第三步超过32位四舍五入得到
0,10011101,11011100110101100101000,这就得到上面的值了(上面的值第一位0隐藏了)。
所以2000000000f == 2000000050f是true。这下是不是理解了。去考考你的同学和同事,让他们怀疑一下自己的编程人生(大牛除外😄)。

最后留一个问题0.1 + 0.2 == 0.3吗?之前讲过哦。

目录
打赏
0
0
0
0
2
分享
相关文章
指针不过如此,看完后我差点飘了(二)
指针不过如此,看完后我差点飘了
151 0
带你读书之“红宝书”:第十章 函数⑥
带你读书之“红宝书”:第十章 函数⑥
95 0
带你读书之“红宝书”:第十章 函数⑥
第七回(二):遇莽夫之见悟文章 听《夕阳之歌》伤名伶
(二)第七回:  遇莽夫之见悟文章    听《夕阳之歌》伤名伶       谁想林二静中生烦恼,忽一日不自在起来。想来这几日未见莉莉,便觉这也不好,那也不好。众人招呼去蹴鞠场,也不理睬。教室出来进去只是闷闷的。
889 0
带你读书之“红宝书”:第十章 函数⑦
带你读书之“红宝书”:第十章 函数⑦
122 0
带你读书之“红宝书”:第十章 函数⑦
一辈子交186万五险一金!退休你能拿回多少?算完惊呆……
不知道大家有没有算过,从毕业工作一直到退休,每个月缴纳的五险一金和个税,加起来一共有多少钱? 小编帮你算了一下,貌似可以整套房了…… 那你退休几年后能回本呢? 按2017年上海职工平均工资(6504元)来计算每月缴纳的五险一金和个税如下 im...
1210 0

热门文章

最新文章

AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等