获得root权限-搜狗 360
![decimalformat](/uploads/image/0472.jpg)
2023年4月3日发(作者:网络延迟测试)
java保留两位⼩数
java保留两位⼩数问题:
⽅式⼀:
四舍五⼊
doublef=111231.5585;
BigDecimalb=newBigDecimal(f);
doublef1=le(2,_HALF_UP).doubleValue();
保留两位⼩数
---------------------------------------------------------------
⽅式⼆:
lFormatdf=lFormat("#.00");
(你要格式化的数字);
例:lFormat("#.00").format(3.1415926)
#.00表⽰两位⼩数#.0000四位⼩数以此类推...
⽅式三:
doubled=3.1415926;
Stringresult=("%.2f");
%.2f%.表⽰⼩数点前任意位数2表⽰两位⼩数格式后的结果为f表⽰浮点型
⽅式四:
NumberFormatddf1=berInstance();
voidsetMaximumFractionDigits(intdigits)
digits显⽰的数字位数
为格式化对象设定⼩数点后的显⽰的最多位,显⽰的最后位是舍⼊的
.*;
.*;
classTT
{
publicstaticvoidmain(Stringargs[])
{doublex=23.5455;
NumberFormatddf1=berInstance();
imumFractionDigits(2);
Strings=(x);
(s);
}
}
---------------------------------------------------------------------------------------------------------
有⼀篇:
(1)、浮点数精确计算
胜利油⽥三流合⼀项⽬中⼀直存在⼀个问题,就是每次报表统计的物资⾦额和实际的⾦额要差那么⼏分钱,和实际⾦额不⼀致,让客户
觉得总是不那么舒服,原因是因为我们使⽤java的浮点类型double来定义物资⾦额,并且在报表统计中我们经常要进⾏⼀些运算,但Java中
浮点数(double、float)的计算是⾮精确计算,请看下⾯⼀个例⼦:
n(0.05+0.01);
n(1.0-0.42);
n(4.015*100);
n(123.3/100);
你的期望输出是什么?可实际的输出确实这样的:
0.000005
0.5801
401.49999999999994
1.2329999999999999
这个问题就⾮常严重了,如果你有123.3元要购买商品,⽽计算机却认为你只有123.29999999999999元,钱不够,计算机拒绝交易。
(2)、四舍五⼊
是否可以四舍五⼊呢?当然可以,习惯上我们本能就会这样考虑,但四舍五⼊意味着误差,商业运算中可能意味着错误,同时Java中也
没有提供保留指定位数的四舍五⼊⽅法,只提供了⼀个(doubled)和(floatf)的⽅法,分别返回长整型和整型
值。round⽅法不能设置保留⼏位⼩数,我们只能象这样(保留两位):
publicdoubleround(doublevalue){
(value*100)/100.0;
}
但⾮常不幸的是,上⾯的代码并不能正常⼯作,给这个⽅法传⼊4.015它将返回4.01⽽不是4.02,如我们在上⾯看到的
4.015*100=401.49999999999994
因此如果我们要做到精确的四舍五⼊,这种⽅法不能满⾜我们的要求。
还有⼀种⽅式是使⽤lFormat,但也存在问题,format采⽤的舍⼊模式是ROUND_HALF_DOWN(舍⼊模式在下⾯有介
绍),⽐如说4.025保留两位⼩数会是4.02,因为.025距离”nearestneighbor”(.02和.03)长度是相等,向下舍⼊就是.02,如果是4.0251那
么保留两位⼩数就是4.03。
n(lFormat("0.00").format(4.025));
n(lFormat("0.00").format(4.0251));
输出是
4.02
4.03
(3)、浮点数输出(科学记数法)
Java浮点型数值在⼤于9999999.0就⾃动转化为科学记数法来表⽰,我们看下⾯的例⼦:
n(999999999.04);
n(99999999.04);
n(10000000.01);
n(9999999.04);
输出的结果如下:
9.9999999904E8
9.999999904E7
1.000000001E7
9999999.04
但有时我们可能不需要科学记数法的表⽰⽅法,需要转换为字符串,还不能直接⽤toString()等⽅法转换,很烦琐。
BigDecimal介绍
BigDecimal是Java提供的⼀个不变的、任意精度的有符号⼗进制数对象。它提供了四个构造器,有两个是⽤BigInteger构造,在这⾥我
们不关⼼,我们重点看⽤double和String构造的两个构造器(有关BigInteger详细介绍请查阅j2seAPI⽂档)。
BigDecimal(doubleval)
TranslatesadoubleintoaBigDecimal.
BigDecimal(val)
TranslatestheStringrepresentationofaBigDecimalintoaBigDecimal.
BigDecimal(double)是把⼀个double类型⼗进制数构造为⼀个BigDecimal对象实例。
BigDecimal(String)是把⼀个以String表⽰的BigDecimal对象构造为BigDecimal对象实例。
习惯上,对于浮点数我们都会定义为double或float,但BigDecimalAPI⽂档中对于BigDecimal(double)有这么⼀段话:
Note:htassumethatnewBigDecimal(.1)isexactlyequalto.1,butitisactuallyequalto
.sobecause.1cannotberepresentedexactlyasadouble(or,forthatmatter,asabinaryfractionof
anyfinitelength).Thus,thelongvaluethatisbeingpassedintotheconstructorisnotexactlyequalto.1,appearancesnotwithstanding.
The(String)constructor,ontheotherhand,isperfectlypredictable:newBigDecimal(".1")isexactlyequalto.1,ore,itisgenerallyrecommendedthat
the(String)constructorbeusedinpreferencetothisone
下⾯对这段话做简单解释:
注意:这个构造器的结果可能会有不可预知的结果。有⼈可能设想newBigDecimal(.1)等于.1是正确的,但它实际上是等
于.41015625,这就是为什么.1不能⽤⼀个double精确表⽰的
原因,因此,这个被放进构造器中的长值并不精确的等于.1,尽管外观看起来是相等的。
然⽽(String)构造器,则完全可预知的,newBigDecimal(“.1”)如同期望的那样精确的等于.1,因此,(String)构造器是被优先
推荐使⽤的。
看下⾯的结果:
n(newBigDecimal(123456789.02).toString());
n(newBigDecimal("123456789.02").toString());
输出为:
123456789.67486572265625
123456789.02
现在我们知道,如果需要精确计算,⾮要⽤String来够造BigDecimal不可!
实现⽅案
现在我们已经知道怎么解决这个问题了,原则上是使⽤BigDecimal(String)构造器,我们建议,在商业应⽤开发中,涉及⾦额等浮点
数计算的数据,全部定义为String,数据库中可定义为字符型字段,在需要使⽤这些数据进⾏运算的时候,使⽤BigDecimal(String)构
造BigDecimal对象进⾏运算,保证数据的精确计算。同时避免了科学记数法的出现。如果科学记数表⽰法在应⽤中不是⼀种负担的话,可以
考虑定义为浮点类型。
这⾥我们提供了⼀个⼯具类,定义浮点数的加、减、乘、除和四舍五⼊等运算⽅法。以供参考。
源⽂件:
imal;
publicclassMathExtend
{
//默认除法运算精度
privatestaticfinalintDEFAULT_DIV_SCALE=10;
/**
*提供精确的加法运算。
*@paramv1
*@paramv2
*@return两个参数的和
*/
publicstaticdoubleadd(doublev1,doublev2)
{
BigDecimalb1=newBigDecimal(ng(v1));
BigDecimalb2=newBigDecimal(ng(v2));
(b2).doubleValue();
}
/**
*提供精确的加法运算
*@paramv1
*@paramv2
*@return两个参数数学加和,以字符串格式返回
*/
publicstaticStringadd(Stringv1,Stringv2)
{
BigDecimalb1=newBigDecimal(v1);
BigDecimalb2=newBigDecimal(v2);
(b2).toString();
}
/**
*提供精确的减法运算。
*@paramv1
*@paramv2
*@return两个参数的差
*/
publicstaticdoublesubtract(doublev1,doublev2)
{
BigDecimalb1=newBigDecimal(ng(v1));
BigDecimalb2=newBigDecimal(ng(v2));
ct(b2).doubleValue();
}
/**
*提供精确的减法运算
*@paramv1
*@paramv2
*@return两个参数数学差,以字符串格式返回
*/
publicstaticStringsubtract(Stringv1,Stringv2)
{
BigDecimalb1=newBigDecimal(v1);
BigDecimalb2=newBigDecimal(v2);
ct(b2).toString();
}
/**
*提供精确的乘法运算。
*@paramv1
*@paramv2
*@return两个参数的积
*/
publicstaticdoublemultiply(doublev1,doublev2)
{
BigDecimalb1=newBigDecimal(ng(v1));
BigDecimalb2=newBigDecimal(ng(v2));
ly(b2).doubleValue();
}
/**
*提供精确的乘法运算
*@paramv1
*@paramv2
*@return两个参数的数学积,以字符串格式返回
*/
publicstaticStringmultiply(Stringv1,Stringv2)
{
BigDecimalb1=newBigDecimal(v1);
BigDecimalb2=newBigDecimal(v2);
ly(b2).toString();
}
/**
*提供(相对)精确的除法运算,当发⽣除不尽的情况时,精确到
*⼩数点以后10位,以后的数字四舍五⼊,舍⼊模式采⽤ROUND_HALF_EVEN
*@paramv1
*@paramv2
*@return两个参数的商
*/
publicstaticdoubledivide(doublev1,doublev2)
{
returndivide(v1,v2,DEFAULT_DIV_SCALE);
}
/**
*提供(相对)精确的除法运算。当发⽣除不尽的情况时,由scale参数指
*定精度,以后的数字四舍五⼊。舍⼊模式采⽤ROUND_HALF_EVEN
*@paramv1
*@paramv2
*@paramscale表⽰需要精确到⼩数点以后⼏位。
*@return两个参数的商
*/
publicstaticdoubledivide(doublev1,doublev2,intscale)
{
returndivide(v1,v2,scale,_HALF_EVEN);
}
/**
*提供(相对)精确的除法运算。当发⽣除不尽的情况时,由scale参数指
*定精度,以后的数字四舍五⼊。舍⼊模式采⽤⽤户指定舍⼊模式
*@paramv1
*@paramv2
*@paramscale表⽰需要精确到⼩数点以后⼏位
*@paramround_mode表⽰⽤户指定的舍⼊模式
*@return两个参数的商
*/
publicstaticdoubledivide(doublev1,doublev2,intscale,intround_mode){
if(scale<0)
{
thrownewIllegalArgumentException("Thescalemustbeapositiveintegerorzero");
}
BigDecimalb1=newBigDecimal(ng(v1));
BigDecimalb2=newBigDecimal(ng(v2));
(b2,scale,round_mode).doubleValue();
}
/**
*提供(相对)精确的除法运算,当发⽣除不尽的情况时,精确到
*⼩数点以后10位,以后的数字四舍五⼊,舍⼊模式采⽤ROUND_HALF_EVEN
*@paramv1
*@paramv2
*@return两个参数的商,以字符串格式返回
*/
publicstaticStringdivide(Stringv1,Stringv2)
{
returndivide(v1,v2,DEFAULT_DIV_SCALE);
}
/**
*提供(相对)精确的除法运算。当发⽣除不尽的情况时,由scale参数指
*定精度,以后的数字四舍五⼊。舍⼊模式采⽤ROUND_HALF_EVEN
*@paramv1
*@paramv2
*@paramscale表⽰需要精确到⼩数点以后⼏位
*@return两个参数的商,以字符串格式返回
*/
publicstaticStringdivide(Stringv1,Stringv2,intscale)
{
returndivide(v1,v2,DEFAULT_DIV_SCALE,_HALF_EVEN);
}
/**
*提供(相对)精确的除法运算。当发⽣除不尽的情况时,由scale参数指
*定精度,以后的数字四舍五⼊。舍⼊模式采⽤⽤户指定舍⼊模式
*@paramv1
*@paramv2
*@paramscale表⽰需要精确到⼩数点以后⼏位
*@paramround_mode表⽰⽤户指定的舍⼊模式
*@return两个参数的商,以字符串格式返回
*/
publicstaticStringdivide(Stringv1,Stringv2,intscale,intround_mode)
{
if(scale<0)
{
thrownewIllegalArgumentException("Thescalemustbeapositiveintegerorzero");
}
BigDecimalb1=newBigDecimal(v1);
BigDecimalb2=newBigDecimal(v2);
(b2,scale,round_mode).toString();
}
/**
*提供精确的⼩数位四舍五⼊处理,舍⼊模式采⽤ROUND_HALF_EVEN
*@paramv需要四舍五⼊的数字
*@paramscale⼩数点后保留⼏位
*@return四舍五⼊后的结果
*/
publicstaticdoubleround(doublev,intscale)
{
returnround(v,scale,_HALF_EVEN);
}
/**
*提供精确的⼩数位四舍五⼊处理
*@paramv需要四舍五⼊的数字
*@paramscale⼩数点后保留⼏位
*@paramround_mode指定的舍⼊模式
*@return四舍五⼊后的结果
*/
publicstaticdoubleround(doublev,intscale,intround_mode)
{
if(scale<0)
{
thrownewIllegalArgumentException("Thescalemustbeapositiveintegerorzero");
}
BigDecimalb=newBigDecimal(ng(v));
le(scale,round_mode).doubleValue();
}
/**
*提供精确的⼩数位四舍五⼊处理,舍⼊模式采⽤ROUND_HALF_EVEN
*@paramv需要四舍五⼊的数字
*@paramscale⼩数点后保留⼏位
*@return四舍五⼊后的结果,以字符串格式返回
*/
publicstaticStringround(Stringv,intscale)
{
returnround(v,scale,_HALF_EVEN);
}
/**
*提供精确的⼩数位四舍五⼊处理
*@paramv需要四舍五⼊的数字
*@paramscale⼩数点后保留⼏位
*@paramround_mode指定的舍⼊模式
*@return四舍五⼊后的结果,以字符串格式返回
*/
publicstaticStringround(Stringv,intscale,intround_mode)
{
if(scale<0)
{
thrownewIllegalArgumentException("Thescalemustbeapositiveintegerorzero");
}
BigDecimalb=newBigDecimal(v);
le(scale,round_mode).toString();
}
}
BigDecimal舍⼊模式(Roundingmode)介绍:
BigDecimal定义了⼀下舍⼊模式,只有在作除法运算或四舍五⼊时才⽤到舍⼊模式,下⾯简单介绍,详细请查阅J2seAPI⽂档
staticint
ROUND_CEILING
Roundingmodetoroundtowardspositiveinfinity.
向正⽆穷⽅向舍⼊
staticint
ROUND_DOWN
Roundingmodetoroundtowardszero.
向零⽅向舍⼊
staticint
ROUND_FLOOR
Roundingmodetoroundtowardsnegativeinfinity.
向负⽆穷⽅向舍⼊
staticint
ROUND_HALF_DOWN
Roundingmodetoroundtowards"nearestneighbor"unlessbothneighborsareequidistant,inwhichcaserounddown.
向(距离)最近的⼀边舍⼊,除⾮两边(的距离)是相等,如果是这样,向下舍⼊,例如1.55保留⼀位⼩数结果为1.5
staticint
ROUND_HALF_EVEN
Roundingmodetoroundtowardsthe"nearestneighbor"unlessbothneighborsareequidistant,inwhichcase,round
towardstheevenneighbor.
向(距离)最近的⼀边舍⼊,除⾮两边(的距离)是相等,如果是这样,如果保留位数是奇数,使⽤ROUND_HALF_UP,如果是
偶数,使⽤ROUND_HALF_DOWN
staticint
ROUND_HALF_UP
Roundingmodetoroundtowards"nearestneighbor"unlessbothneighborsareequidistant,inwhichcaseroundup.
向(距离)最近的⼀边舍⼊,除⾮两边(的距离)是相等,如果是这样,向上舍⼊,1.55保留⼀位⼩数结果为1.6
staticint
ROUND_UNNECESSARY
Roundingmodetoassertthattherequestedoperationhasanexactresult,hencenoroundingisnecessary.
计算结果是精确的,不需要舍⼊模式
staticint
ROUND_UP
Roundingmodetoroundawayfromzero.
向远离0的⽅向舍⼊
更多推荐
decimalformat
发布评论