bigdecimal比较大于0,double转bigdecimal
【转载】原文链接: https://blog.csdn.net/lk force/article/details/81564927
以上结论:不要直接使用双精度变量作为构建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”) createsabigdecimalwhichises asonewouldexpect.Thich itisgenerallyrecommendedthatthestringconstructorbeusedinpreferencetothisone。
whenadoublemustbeusedasasourceforabigdecimal,notethatthisconstructorprovidesanexactconversion; itdoesnotgivethesameresultasconvertingthedoubletoastringusingthedouble.tostring (double ) methodandthenusingthebigdecimal (
Parameters:
val-doublevaluetobeconvertedtobigdecimal。
Throws:
numberformatexception-ifvalisinfiniteornan。
翻译后大致如下:
1,BigDecimal(doubleval )结构,以double为参数构建bigdecimal对象。
2但是这个结构不太可靠。 (unpredictable )、bigdecimal )、0.1 )你可能认为完全等于0.1,你认为你想的是什么? 不,bigdecimal(0.1 )这个商品实际上等于0.100000000005111511231257827021183404541015625。 因为准确地说0.1本身不能说是double。 (实际上,0.1不能表示任意定长二进制。
3,bigdecimal(stringval )结构可靠。 bigdecimal )“0.1”完全等于0.1。 推荐这个结构。
4 )如果你必须使用double变量构建BigDecimal,没关系。 我们亲切地提供静态的方法value of (双精度)。 此方法与newdecimal ) double.tostring (double ) )具有相同的效果。
简言之,最好使用String类型作为参数,或者使用静态方法valueOf(double ),而不是直接将double变量作为参数。 我写了一个例子:
publicstaticvoidmain (字符串[ ] args ) { float a=57.3f; bigdecimaldecimala=new bigdecimal (a; system.out.println(decimala; 双精度b=57.3; bigdecimaldecimalb=new bigdecimal (b; system.out.println(decimalb; 双精度c=57.3; bigdecimaldecimalc=new bigdecimal (double.tostring (c ); system.out.println(decimalc; 双精度d=57.3; bigdecimaldecimald=bigdecimal.value of (d; system.out.println(decimald; }输出结果:
57.299999237060546875
57.299999999999971578290569595999256515029296875
57.3
57.3
今后请尽量按照官方推荐的那样做。 否则,不知道什么时候又会给自己挖洞。