天天看点

谁是代码界3%的王者?- 第四题BigDecimal问题简单解读

提到“在Java代码界,有些陷阱外表看起来是个青铜实际上是王者,据说97%工程师会被“秒杀””

给出了五道题,非常考验基础。

本文简单解读第4题,并分享通用的学习和研究方法。

题目配套代码

题目内容

下列哪种说法是正确的:

A: 两种赋值的方式是一样的

B: 推荐a的赋值方式

C: 推荐b的赋值方式

先公布答案:C

上面源代码输出的效果如下

0.1000000000000000055511151231257827021181583404541015625

显然b是我们想要的效果

java.math.BigDecimal#BigDecimal(java.lang.String)

人家都怕你不仔细看给了你那么多示例,还专门给了一个note

此构造函数是float或double转到BigDecimal的推荐方式,因为该构造方法不会像BigDecimal(double)一样会有一些不可预测的情况。

它最终调用了java.math.BigDecimal#BigDecimal(char[], int, int) 感兴趣大家可以自己去看。

我们再看另外一个构造函数

java.math.BigDecimal#BigDecimal(double)

专门提到

这是因为double类型无法精确表示0.1。因此传入0.1参数到该构造方法其实并不精确等于0.1。

更推荐使用参数为String的构造方法,换句话说用BigDecimal("0.1")来构造完全等于0.1的BigDecimal。 因此,推荐带String参数的构造方法。

如果必须把double作为构造方法的参数时,注意和new BigDecimal(Double.toString(0.1d))的结果是完全不同的。

因此答案就不言而喻了。

计算机通过二进制来存储数据,双精度8字节(64位)的表示

谁是代码界3%的王者?- 第四题BigDecimal问题简单解读

其中第63索引位,共1位,表示符号位(sign bit),用s表示;0表示正数,1表示负数

第52到62索引位,共11位,表示指数(signed exponent),用e表示;2的多少次方

第51到0索引位(significant/mantissa value),共52位,表示小数部分,用m表示;有效位

浮点型:https://docs.oracle.com/cd/E19957-01/806-3568/ncg_math.html

十进制无法表示三分之一,二进制无法表示十分之一。

像三分之一一样,三分之一无法用有限个十进制数表示。10的-1次幂(0.1)不是有限个2的幂的和,所以不能用有限个2进制位表示,而double是8字节的,只有64位,是有限个二进制数,因此无法精确表示0.1。

正如前面的几个问题解答中我提到的几个常见方法一样,这类问题我们最好的办法是看源码!看源码的注释!!

看官方文档!!看权威规范!!(如本文提到的《IEEE Arithmetic》的网页)。

另外一个启发是计算机专业基础要扎实!!!二进制要理解的透彻一些。

开发的时候尽量多去源码里看注释!!!

附录

《谁是代码界3%的王者?- 第三题switch问题简单解读》

《谁是代码界3%的王者?- 第五题Lock的简单解读》