首页天道酬勤integer转bigdecimal,bigdecimal转int

integer转bigdecimal,bigdecimal转int

张世龙 05-06 11:06 37次浏览

以上结论:不要直接使用双精度变量作为构建BigDecimal的参数。

在线上有以下Java代码逻辑:

1、界面传来了JSON的字符串,里面有数字。 57.3。

2 )解析JSON,将该数字保存在一个float变量中。

3,将这个浮点变量代入BigDecimal对象。 使用BigDecimal双精度参数的结构:

新双精度。

4 .将此BigDecimal保存到MySQL数据库中。 字段类型为decimal (15,2 )。

这个代码逻辑在线运行了很长时间,但存储在数据库中的值为57.3也没问题。 但是,在今天的调试时,步骤3中存储在BigDecimal对象中的值为57.299999237060546875,而不是57.3,这显然导致了精度问题。

数据库最终保存正确的57.3是因为字段类型设置为两位小数,如果超过两位小数,则会进行四舍五入,因此得到了正确的结果。 和MySQL掩盖了这个精度问题一样。

我总觉得这是个漏洞,所以研究了相关知识。

首先是BigDecimal的双精度参数结构。 在官方JDK文档中,该结构描述如下:

公共二进制(双精度)。

translatesadoubleintoabigdecimalwhichistheexactdecimalrepresentationofthedouble ' sbinaryfloating-point value.thescaleofthe

Notes:

theresultsofthisconstructorcanbesomewhatunpredictable.onemightassumethatwritingnewbigdecimal (0.1 ) )。 injavacreatesabigdecimalwhichisexactlyequalto 0.1 (anunscaledvalueof 1,with a scale of 1), utitisactuallyequalto 0.1000000000005115123125782702118340451015625.this is because 0.1 cannotberepresentedexactlyas asabinaryfractionofanyfinitelength, Thus,thevaluethatisbeingpassedintotheconstructorisnotexactlyequater

The String constructor,on the other hand,isperfectlypredictable : writingnewbigdecimal (0.1 ) ) createsabigdecimalwhisexable asonewouldexpect.Thich itisgenerallyrecommendedthatthestringconstructorbeusedinpreferencetothisone。

When a double must be used as a sour

ce 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.

Parameters:

val - double value to be converted to BigDecimal.

Throws:

NumberFormatException - if val is infinite or NaN.

翻译一下大概是这样的:

1,BigDecimal(double val)构造,用double当参数来构造一个BigDecimal对象。

2,但是这个构造不太靠谱(unpredictable),你可能以为BigDecimal(0.1)就是妥妥的等于0.1,但是你以为你以为的就是你以为的?还真不是,BigDecimal(0.1)这货实际上等于0.1000000000000000055511151231257827021181583404541015625,因为准确的来说0.1本身不能算是一个double(其实0.1不能代表任何一个定长二进制分数)。

3,BigDecimal(String val)构造是靠谱的,BigDecimal(“0.1”)就是妥妥的等于0.1,推荐大家用这个构造。

4,如果你非得用一个double变量来构造一个BigDecimal,没问题,我们贴心的提供了静态方法valueOf(double),这个方法跟new Decimal(Double.toString(double))效果是一样的。

 

说白了就是别直接拿double变量做参数,最好使用String类型做参数或者使用静态方法valueOf(double),我写了个例子试了一下:

         public static void main(String[] args) {                   float a=57.3f;                   BigDecimal decimalA=new BigDecimal(a);                   System.out.println(decimalA);                                     double b=57.3;                   BigDecimal decimalB=new BigDecimal(b);                   System.out.println(decimalB);                                     double c=57.3;                   BigDecimal decimalC=new BigDecimal(Double.toString(c));                   System.out.println(decimalC);                                     double d=57.3;                   BigDecimal decimalD=BigDecimal.valueOf(d);                   System.out.println(decimalD);         }

 

输出结果:

57.299999237060546875

57.2999999999999971578290569595992565155029296875

57.3

57.3

以后还是尽量按照官方推荐的套路来,否则不知道什么时候又给自己挖坑了。

 

bigdecimal转double精度变了,字符串转bigdecimal类型