Java中double转BigDecimal的注意事项
问题现象:精度丢失。发现是使用new BigDecimal(double d)这种形式去计算的。
double d=0.1;
BigDecimal d1= new BigDecimal(d) d1在计算机存储中,
并不是0.1。而是类似0.1000000000000000033等这种形式。
官方文档:
BigDecimal构造函数:
the results of this constructor can be somewhat unpredictable.
* One might assume that writing {@code new BigDecimal(0.1)} in
* Java creates a {@code 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
* {@code 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.
翻译总结:使用new BigDecimal(double d)这种构造是不可预测,不可靠的
解决方案&总结
- BigDecimal(double val)构造,用double当参数来构造一个BigDecimal对象。这种并不靠谱。不推荐。
- BigDecimal(String val)构造是靠谱的,BigDecimal(“0.1”)就是妥妥的等于0.1,推荐大家用这个构造。
- 如果你非得用一个double变量来构造一个BigDecimal,没问题,我们贴心的提供了静态方法valueOf(double),这个方法跟new Decimal(Double.toString(double))效果是一样的。
一次线上java服务outOfmemory分析
- docker部署,线上日志出现outOfmemoryError。
分析思路
- 看一下监控。发现报错的瞬间,网卡流量飙升。怀疑是sql等的问题。导出堆栈信息,然后使用mat分析工具进行分析,发现大对象是sql查询。进而找到对应的sql语句。上游db表,数据量太大。100多万条,join查询后,直接长时间无响应。
- 此外,日志排查很重要,在outOfMemoryError之前的日志。基本上就已经标明了有问题的地方。