BigDecimal和Double的一些问题

今天发现, 当我们有一个Double类型的变量, 想把它转换成BigDecimal进行计算时,不能用new BigDecimal(double), 而是应该用BigDecimal.valueOf(double), 前者返回的数值不精确。

例如:

new BigDecimal(10.0).multiply(new BigDecimal(0.15))

会得到1.49, 而

BigDecimal.valueOf(10.0).multiply(BigDecimal.valueOf(0.15))

会得到1.50。

额外说一点,BigDecimal.valueOf(double)是这样的逻辑:

return new BigDecimal(Double.toString(val));

先转成String, 再new这个对象.

而MyBatis在转换BigDecimal时用到的BigDecimalTypeHandler是这样的:

 @Override
  public BigDecimal getNullableResult(ResultSet rs, String columnName)
      throws SQLException {
    return rs.getBigDecimal(columnName);
  }

 public BigDecimal getBigDecimal(int columnIndex) throws SQLException {
    if (!this.isBinaryEncoded) {
      String stringVal = this.getString(columnIndex);
      if (stringVal != null) {
        BigDecimal val;
        if (stringVal.length() == 0) {
          val = new BigDecimal(this.convertToZeroLiteralStringWithEmptyCheck());
          return val;
        } else {
          try {
            val = new BigDecimal(stringVal);
            return val;
          } catch (NumberFormatException var5) {
            throw SQLError.createSQLException(Messages.getString("ResultSet.Bad_format_for_BigDecimal", new Object[]{stringVal, columnIndex}), "S1009", this.getExceptionInterceptor());
          }
        }
      } else {
        return null;
      }
    } else {
      return this.getNativeBigDecimal(columnIndex);
    }
  }

调用的是this.getString() 和this.convertToZeroLiteralStringWithEmptyCheck(), 先得到列的String值再new BigDecimal(), 所以MyBatis中可以放心使用BigDecimal不会出现误差。

你可能感兴趣的:(BigDecimal和Double的一些问题)