Java面试官:double精度真的比float低吗?

Wesley13
• 阅读 616

Java面试官:double精度真的比float低吗?

我有一个朋友,叫老刘,戴着度数比我还高的近视镜,显得格外的“程序员”;穿着也非常“不拘一格”,上半身是衬衣西服,下半身是牛仔裤运动鞋。

我和老刘的感情非常好,每周末我们都要在一起吃顿饭。这周,我们吃的是洛阳有名的吴家刀削面,席间他聊了一件蛮有趣的面试经历;我听得津津有味。

散席的时候,老刘特意叮嘱我把他和面试者的对话整理一下发出来,因为他觉得这段对话非常的精彩,值得推荐给更多初学Java的年轻人。

注:以下是老刘和面试者东丰的真实对话。如有雷同,请勿对号入座。

老刘:“东丰,你长期从事金融软件的开发,记录存款和金额之类的有关数据用哪种数据类型啊?”

东丰:“当然用float啊,精确度比double高嘛。”

老刘:“东丰,你确定double精度比float低吗?”

东丰:“那当然啊,double只精确到小数点后两位,double这个单词的意思不就是二的意思吗?”

老刘:“东丰,你右手边刚好有一本《Java核心技术卷1》,你翻到第35页,看一下。”

东丰:“……哦,刘经理,不用了。不好意思,刚刚开个玩笑,为了缓和一下面试的紧张气氛。看您厚厚的眼镜片下藏着一双深邃的眼睛,我觉得您一定大有学问。在金融计算中,必须要使用BigDecimal,double和float都不适合。因为单单一个精度问题就能把人整晕了。”

“我记得有一次,我碰巧要计算一个表达式a - b,a的值为2,b的值为1.1,我侄女五岁半都知道答案应该是0.9,结果程序算出来的结果竟然是0.89999…,我当时又气又激动,气的是计算机还没有我侄女靠谱,激动的是我竟然第一次找到了Java的bug。”

“我赶紧把这个bug反馈到了沉默王二的青铜时代群,以为我要被大家点赞表扬了。结果收到了大佬们一致的无情的嘲笑!”

“好在,群主二哥及时地安慰了我。他发我信息说:‘首先,计算机进行的是二进制运算,我们输入的十进制数字会先转换成二进制,进行运算后再转换为十进制输出。double和float提供了快速的运算,然而问题在于转换为二进制的时候,有些数字不能完全转换,只能无限接近于原本的值,这就导致了你看到的不正确的结果。’”

“看到二哥的信息后,我沮丧的心情得到了很大的安慰。我于是就对使用浮点数和小数中的问题进行了深入地研究。”

“BigDecimal可以表示任意精度的小数,并对它们进行计算。但要小心使用 BigDecimal(double) 构造函数,因为它会在计算的过程中产生舍入误差。最好要使用基于整数或 String 的构造函数来创建BigDecimal对象。”

老刘:“哇,你回答得很好。那我们来看下一个问题。你应该知道2 / 0的时候程序会报java.lang.ArithmeticException的错误,那么你知道2.0 / 0的结果吗?”

东丰:“刘经理,您这个问题难不倒我。结果是Infinity(英菲尼迪),不好意思,我的英语口语能力有限啊。其实就是无穷的意思。不仅有正无穷大,还有负无穷大,甚至还有一个叫做NaN的特殊值。NaN代表‘不是一个数字’。这些值的存在是为了在出现错误条件时,程序还可以用特定的值来表示所产生的结果。这些错误的情况包括算术溢出、给负数开平方根,还有您说的除以 0 等。”

老刘:“东丰啊,你的发音比我好啊,挺准确的。”

东丰:“刘经理您见笑了。”

老刘:“我这还有一道关于数组的问题,你稍等一下,我在纸上写一下。”

int[] a = {1, 2, 3, 4}int[] b = {2, 4}int[] c = {1, 3}int[] d = {2}

“有这样四个数组,要求每个数组只留一个唯一的元素。也就是说,a、b、c、d四个数组之间的元素不能相同,你打算怎么做呢?”

东丰:“刘经理,我能用一下您的凌美钢笔吗?”

老刘:“可以啊,你请用。”

东丰:“我大致演算了一下。说一下我的思路。d只能是2,b只能是4,a是1或者3,c是3或者1。遍历长数组,剔除长数组中含有的最短数组的元素。b中剔除d中的2还剩下4,a中剔除d中的2还剩下1、3、4,c中不含d中元素,所以不用剔除。剔除后b中还剩下一个4,d中是一个2。再次遍历剔除a中的4。最后a和c中只剩下1和3了,再分别剔除互异的数就行了。”

“我觉得比较笨的作法,刘经理您觉得可行吗?”

_附「沉默王二一群(青铜时代)一位王浩同学的解决方案」_:

import java.util.ArrayList;public class Distinct {    public static void main(String[] args) {        int[] a = {1, 2, 3, 4};        int[] b = {2, 4};        int[] c = {1, 3};        int[] d = {2};        int[][] input = {a, b, c, d};         //记录每个数组留下的唯一的元素        ArrayList<Integer> result = new ArrayList<Integer>();        //记录每个数组留下的唯一元素在数组中的位置        ArrayList<Integer> index = new ArrayList<Integer>();         int row = 0;        int column = 0;        do {            boolean isBacktrack = false; //记录当前状态,是否是回溯            while(column < input[row].length) {                Integer current = input[row][column];                //当前元素是否已存在结果集中                boolean isContained = result.contains(current);;                //若当前元素不存在结果集中,将该元素加入结果集,并遍历下一行                if(isContained == false) {                    result.add(current);                    index.add(column);                    column = 0;                    row++;                    break;                }                //如果当前元素已经存在结果集中,并且已经到达本行最后一个元素,则回溯一行                else if(column + 1 == input[row].length) {                    result.remove(result.size() - 1);                    column = index.get(index.size() - 1) + 1;                    index.remove(index.size() - 1);                    row--; //回溯一行                    isBacktrack = true;                    break;                }                column++;            }            //如果是回溯,判断列数是否超过该行的界限,如果超过了,再回溯一行            if(isBacktrack && column == input[row].length) {                result.remove(result.size() - 1);                column = index.get(index.size() - 1) + 1;                index.remove(index.size() - 1);                row--; //回溯一行                isBacktrack = true;            }        }while(row < input.length);        //把 result 中的每个元素赋给相应的数组        for(int i = 0; i < result.size(); i++) {            input[i] = new int[] {result.get(i)};        }        //打印每个数组的元素        for(int[] i: input) {            System.out.println(i[0]);        }    }}

老刘:“可行,没有问题。那,你对变量和方法的命名有什么看法呢?请随意发挥啊。”

东丰:“我在博客园上曾看到一个有意思的投票统计——选出平常工作时自己认为最难的事情,选项大致有:”

  • 写各种文档

  • 与客户沟通

  • 预估工作量

  • 给变量命名

“投票结果完全出乎我的意料,排在第一的竟然是‘给变量命名’!变量命名实在是软件开发中最常见的一件事了,但这件事要想做好,还真是不容易啊。”

“阿里巴巴Java开发手册中「强制」规定,方法名、参数名、成员变量、局部变量要统一使用lowerCamelCase风格,必须遵从驼峰形式。”

localValue // 变量getHttpMessage() // 方法

“有很长一段时间,我总是在纠结究竟是用拼音好还是用英语单词好的问题。后来我下定了决心:要么用拼音要么用英语单词,只要看到名字就能知道这个变量或者方法的用意就行了。”

“有时候,确实很难给变量取一个好名字。这时候,我就会选择一种省时省力省心的做法——将变量名命名为类型名。比如说:”

Map map;List list;

“最好,变量声明的地方要离第一次使用的地方近。否则的话,代码阅读起来会很困难,因为人眼睛接受的屏幕高度是有限的。”

老刘:“东丰啊,你非常的优秀。恭喜你,你的面试过了。你回去准备一下,下周一就可以来上班了。”

再注:以上是老刘和面试者东丰的真实对话。如有雷同,请勿对号入座。

_作者介绍_:沉默王二,一个不止写代码的程序员,还写有趣有益的文字,给不喜欢严肃的你。

作者赞赏码

Java面试官:double精度真的比float低吗?


本文分享自微信公众号 - 沉默王二(cmower)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

点赞
收藏
评论区
推荐文章
待兔 待兔
5个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Stella981 Stella981
3年前
Spring boot源码分析之Spring循环依赖揭秘
!(https://oscimg.oschina.net/oscnet/be79581de12c41704c44e976d329ad35ad1.gif)若你是一个有经验的程序员,那你在开发中必然碰到过这种现象:事务不生效。或许刚说到这,有的小伙伴就会大惊失色了。Spring不是解决了循环依赖问题吗,它是怎么又会发生循环依赖的呢?,接下来就
Stella981 Stella981
3年前
SparkSql学习1 —— 借助SQlite数据库分析2000万数据
总所周知,Spark在内存计算领域非常强势,是未来计算的方向。Spark支持类Sql的语法,方便我们对DataFrame的数据进行统计操作。但是,作为初学者,我们今天暂且不讨论Spark的用法。我给自己提出了一个有意思的思维游戏:Java里面的随机数算法真的是随机的吗?好,思路如下:1\.取样,利用Java代码随机生成2000万条01
Stella981 Stella981
3年前
Android So动态加载 优雅实现与原理分析
背景:漫品Android客户端集成适配转换功能(基于目标识别(So库35M)和人脸识别库(5M)),导致apk体积50M左右,为优化客户端体验,决定实现So文件动态加载.!(https://oscimg.oschina.net/oscnet/00d1ff90e4b34869664fef59e3ec3fdd20b.png)点击上方“蓝字”关注我
Wesley13 Wesley13
3年前
35岁,真的是程序员的一道坎吗?
“程序员35岁是道坎”,“程序员35岁被裁”……这些话咱们可能都听腻了,但每当触及还是会感到丝丝焦虑,毕竟每个人都会到35岁。而国内互联网环境确实对35岁以上的程序员不太友好:薪资要得高,却不如年轻人加班猛;虽说经验丰富,但大部分公司并不需要太资深的程序员。但35岁危机并不是不可避免的,比如你可以不断精进技术,将来做技术管理或者
Wesley13 Wesley13
3年前
37岁程序员失业投500份简历就3次面试猎头:超35岁不要
37岁程序员失业120天,投了500份简历就3次面试,猎头:超过35岁都不要在职场中,都说互联网吃青春饭,而35岁就是一个门槛,一旦到了这个年龄找工作都非常难,甚至被公司裁员的风险都很大,其实一个现象也不难发现,互联网公司几乎都是年轻化,高龄员工很少,这也算行业趋势。最近,一位程序员在职业论坛留言,分享了自己面试的经历,“37岁程序员失业120天,投
Stella981 Stella981
3年前
Linux 是如何管理内存的?
点击蓝色“Java建设者”关注我哟加个“星标”,及时阅读最新技术文章!(https://oscimg.oschina.net/oscnet/df3cbbbafd5ae35c3c30f1b0081db3e740f.png)这是Java建设者第106篇原创文章Linux内存管理模型非常直接明了,因为Lin
Stella981 Stella981
3年前
2021年如何面试大厂?回顾今年字节,美团,华为,蚂蚁等Java岗面试经历!文末直接分享笔记
还有20天就是2021年了,回顾一下2010年自己面试过的大厂,这里我说下我的感受今年跳槽成功的难度比往年高了很多,很明显的感受就是:对于今年的java开发朋友跳槽面试,无论一面还是二面,都开始考验一个Java程序员的技术功底和基础。对源码解读和核心原理理解也是成了加分项,特别是对Java的一些核心基础知识点掌握的不够或者没有体系方向的朋友面试也
Wesley13 Wesley13
3年前
35岁是技术人的天花板吗?
35岁是技术人的天花板吗?我非常不认同“35岁现象”,人类没有那么脆弱,人类的智力不会说是35岁之后就停止发展,更不是说35岁之后就没有机会了。马云35岁还在教书,任正非35岁还在工厂上班。为什么技术人员到35岁就应该退役了呢?所以35岁根本就不是一个问题,我今年已经37岁了,我发现我才刚刚找到自己的节奏,刚刚上路。
可莉 可莉
3年前
2021年如何面试大厂?回顾今年字节,美团,华为,蚂蚁等Java岗面试经历!文末直接分享笔记
还有20天就是2021年了,回顾一下2010年自己面试过的大厂,这里我说下我的感受今年跳槽成功的难度比往年高了很多,很明显的感受就是:对于今年的java开发朋友跳槽面试,无论一面还是二面,都开始考验一个Java程序员的技术功底和基础。对源码解读和核心原理理解也是成了加分项,特别是对Java的一些核心基础知识点掌握的不够或者没有体系方向的朋友面试也