BH4FFUBH4FFU

程序员
业余无线电爱好者

double转bigdecimal精度丢失了?这样写就对了!

0x00 问题

今天发现组内新人使用BigDecimal的构造函数,将double类型转为BigDecimal类型。结果,悲剧了!如下:

   Double d = 0.1;
   System.out.println(d); // 0.1

   BigDecimal bd = new BigDecimal(d);
   System.out.println(bd); // 0.1000000000000000055511151231257827021181583404541015625

眼前的0.1并不是你碎碎念的0.1了...怎么解决呢?

0x01 解决方案

可以使用BigDecimal.valueOf(double),代码如下:

Double d = 0.1;
System.out.println(d); // 0.1

BigDecimal bds = BigDecimal.valueOf(d);
System.out.println(bds); // 0.1

0x02 new BigDecimal(double) vs BigDecimal.valueOf(double)

new BigDecimal(double)

Translates a double into a BigDecimal which is the exact decimal representation of the double's binary floating-point value. The scale of the returned BigDecimal is the smallest value such that (10scale × val) is an integer.

Notes:

  1. The results of this constructor can be somewhat unpredictable. One might assume that writing new BigDecimal(0.1) in Java creates a BigDecimal which is exactly equal to 0.1 (an unscaled value of 1, with a scale of 1), but it is actually equal to 0.1000000000000000055511151231257827021181583404541015625. This is because 0.1 cannot be represented exactly as a double (or, for that matter, as a binary fraction of any finite length). Thus, the value that is being passed in to the constructor is not exactly equal to 0.1, appearances notwithstanding.
  2. The String constructor, on the other hand, is perfectly predictable: writing new BigDecimal("0.1") creates a BigDecimal which is exactly equal to 0.1, as one would expect. Therefore, it is generally recommended that the String constructor be used in preference to this one.
  3. When a double must be used as a source for a BigDecimal, note that this constructor provides an exact conversion; it does not give the same result as converting the double to a String using the Double.toString(double) method and then using the BigDecimal(String) constructor. To get that result, use the static valueOf(double) method.

将double转换为BigDecimal ,这是double的二进制浮点值的精确十进制表示。 返回的BigDecimal是(10scale × val)是一个整数的最小值。
需要注意的是:

  1. 这个构造函数的结果可能有些不可预测。 可以假设在Java中写入new BigDecimal(0.1)创建一个BigDecimal ,它完全等于0.1(非标尺值为1,比例为1),但实际上等于0.1000000000000000055511151231257827021181583404541015625。 这是因为0.1不能像double (或者作为任何有限长度的二进制分数)精确地表示。 因此,正在被传递给构造的值不是正好等于0.1,虽然表面上。
  2. 该String构造,在另一方面,是完全可以预测的:写new BigDecimal("0.1")创建BigDecimal这正好等于0.1,正如人们所期望的那样。 因此, 一般建议使用String constructor优先于此。
  3. 当double必须用作源为BigDecimal ,注意,此构造提供了一个精确的转换; 它不会将double转换为String使用Double.toString(double)方法,然后使用BigDecimal(String)构造函数相同的结果。 要获得该结果,请使用static valueOf(double)方法。

BigDecimal.valueOf(double)

Translates a double into a BigDecimal, using the double's canonical string representation provided by the Double.toString(double) method.
Note: This is generally the preferred way to convert a double (or float) into a BigDecimal, as the value returned is equal to that resulting from constructing a BigDecimal from the result of using Double.toString(double).

转换一个double成BigDecimal ,使用double通过所提供的规范的字符串表示Double.toString(double)方法。
注意:这通常是转换的首选方法double (或float )成BigDecimal ,作为返回的值等于从构建所得BigDecimal使用的结果Double.toString(double) 。

大概不需要多解释了把?

0x03 多说一句

任何技术/工具,用之前请先阅读一下官方文档,就像吃药之前看一下遗嘱或者说明书一样,相同的道理。

下课!

本原创文章未经允许不得转载 | 当前页面:BH4FFU » double转bigdecimal精度丢失了?这样写就对了!

评论 8748

文章评论已关闭!