当前位置:首页 > 生活百科

java百分比用什么类型(java计算百分比代码)

栏目:生活百科日期:2024-12-06浏览:0

BigDecimal

这篇文章我们会介绍一下Java 中的BigDecimal,并且会通过一些例子演示它的用法,例如精度的操作

Java在java.math包中提供的API类BigDecimal,用来对超过16位有效位的数进行精确的运算。双精度浮点型变量double可以处理16位有效数,但在实际应用中,可能需要对更大或者更小的数进行运算和处理。一般情况下,对于那些不需要准确计算精度的数字,我们可以直接使用Float和Double处理,但是Double.valueOf(String) 和Float.valueOf(String)会丢失精度。所以开发中,如果我们需要精确计算的结果,则必须使用BigDecimal类来操作。

为什么需要BigDecimal

前面学习基本类型的时候,我们可以使用float 和 double来表示浮点型数字,但是这里有一个问题那就是基本数据类型float 和 double不应该用于高精度数据的表示,例如货币,因为浮点类型的float 和 double会丢失数据的精度

double d1 = 374.56;double d2 = 374.26;System.out.println( "d1 - d2 = " + ( d1 - d2 ));

这里本应输出的是0.30,但是实际上输出如下

d1 - d2 = 0.30000000000001137

这就是为什么在金融相关的程序里数据类型如此重要的原因,所以我们更好的选择是BigDecimal 而不是float 和 double

Java BigDecimal 类

BigDecimal 是不可变的,任意精度的有符号十进制类型的数字,可用于货币计算

上面那个例子如果我们是使用BigDecimal来代替double 我们可以获得准确的值

BigDecimal bd1 = new BigDecimal("374.56");BigDecimal bd2 = new BigDecimal("374.26");  System.out.println("bd1 - bd2 = " + bd1.subtract(bd2));

现在输出就和预期的一样了

bd1 - bd2 = 0.30

Java 中的BigDecimal类继承自Number并且实现了Comparable接口

public class BigDecimal extends Number implements Comparable&<BigDecimal&> {}

BigDecimal 类的构造方法

BigDecimal 提供了很多的构造方法,可以使用int ,char[],BigDecimal,String,doble ,long,int来初始化BigDecimal,BigDecimal 总共提供了18种构造方法,需要注意的实如果使用double 来初始化BigDecimal或许会再次引入精度的问题,下面提供了一个例子

BigDecimal bde = new BigDecimal(23.12);System.out.println("" + bde.toString());

输出结果是这样的

23.120000000000000994759830064140260219573974609375

Thus it is always safe to go with a constructor that takes String as argument when representing a decimal value.

因此使用String 做为构造函数的参数来表示一个十进制的数字的时候总是安全的

BigDecimal bde = new BigDecimal("23.12");System.out.println("" + bde.toString());

Output

23.12

BigDecimal 的精度

使用BigDecimal的一个理由是BigDecimal提供了精度控制(小数点后的数字的多少)和舍入模式,为了确定小数点后的保留几位数字你可以使用setScale(int scale) 方法,但是最好的是在使用精度的时候提供舍入模式,也就是setScale的重载方法

setScale(int newScale, int roundingMode)setScale(int newScale, RoundingMode roundingMode)

接下来我们通过一个例子演示一下我们为什么要这样做,假设我们在通过一个double值构造一个BigDecimal

BigDecimal bde = new BigDecimal(23.12);System.out.println("Value- " + bde.toString());System.out.println("Scaled value- " + bde.setScale(1).toString());

Output

Value- 23.120000000000000994759830064140260219573974609375Exception in thread "main" java.lang.ArithmeticException: Rounding necessary at java.base/java.math.BigDecimal.commonNeedIncrement(BigDecimal.java:4495) at java.base/java.math.BigDecimal.needIncrement(BigDecimal.java:4702) at java.base/java.math.BigDecimal.pideAndRound(BigDecimal.java:4677) at java.base/java.math.BigDecimal.setScale(BigDecimal.java:2811) at java.base/java.math.BigDecimal.setScale(BigDecimal.java:2853) at org.netjs.Programs.App.main(App.java:15)

从上面的输出中我们看到进度已经丢失了,输出的BigDecimal 是
23.120000000000000994759830064140260219573974609375

并且我们看到当我们将精度设置为1 的时候并且没有提供舍入机制的时候导致Arithmetic异常被抛出

BigDecimal 的舍入模式

如果你注意到了上面我们在讲精度设置的时候,它其实是有两个设置精度的重载方法,第二个参数代表的就是舍入模式模式的参数,BigDecimal提供了八种舍入模式,它们通过static final int 进行表示

public final static int ROUND_UP =           0;public final static int ROUND_DOWN =         1;public final static int ROUND_CEILING =      2;public final static int ROUND_FLOOR =        3;public final static int ROUND_HALF_UP =      4;public final static int ROUND_HALF_DOWN =    5;public final static int ROUND_HALF_EVEN =    6;public final static int ROUND_UNNECESSARY =  7;

需要注意的是在java.math包中也提供舍入模式的枚举值,需要注意的我们是推荐使用枚举值来代替使用int 类型的常量做舍入摸模式的参数

下面我们在设置进度的同时设置一下舍入模式,来避免Arithmetic异常

@Testpublic void scale() {    BigDecimal bde = new BigDecimal(23.12);    System.out.println("Scaled value- " + bde.setScale(1,1).toString());}

但是我们说了,我们推荐使用枚举值的舍入模式,而不是直接使用int 类型的常量,接下来我们看一下RoundingMode 提供的枚举值

CEILING&– Rounding mode to round towards positive infinity.DOWN&– Rounding mode to round towards zero.FLOOR&– Rounding mode to round towards negative infinity.HALF_DOWN&– Rounding mode to round towards &“nearest neighbor&” unless both neighbors are equidistant, in which case round down.HALF_EVEN&– Rounding mode to round towards the &“nearest neighbor&” unless both neighbors are equidistant, in which case, round towards the even neighbor.HALF_UP&– Rounding mode to round towards &“nearest neighbor&” unless both neighbors are equidistant, in which case round up.UNNECESSARY &– Rounding mode to assert that the requested operation has an exact result, hence no rounding is necessary.UP&– Rounding mode to round away from zero.

下面我们通过例子来总结一下这些舍入模式的舍入方式

“java百分比用什么类型(java计算百分比代码)” 的相关文章

如何做好品牌推广方案, 提升品牌知名度的60方法

很多在互联网做产品、做项目的时候,都会做网络营销品牌推广,品牌推广指的是企业塑造自身及产品品牌形象,从而让广大用户和消费者广泛认同的一系列活动和过程。一般来说,...

cad画圆角怎么画(cad圆角的绘制技巧)

我们在绘图的过程中经常都会遇到要绘制圆角矩形的情况,特别是绘制工件图纸的时候,一些零件为了美观或者更好的衔接,都需要将直角变成圆角,绘制圆角的矩形的方法有很多,...

什么牌子洗发水好用,这五款让你不喷香水也能拥有斩男香

现在洗发水品牌众多,除了国外的大品牌,其实国内也有很多好用的,洗发效果也是非常棒的。下面就来分享下那些口碑极佳国产洗发水、还其中有小众洗发水也有知名老国货!洗完...

mysql工具有哪些(mysql性能监控工具和调优)

MySQL备份这是大家经常必须要做的事情,今天网盾科技给大家讲讲MySQL常用的备份方式与备份工具,需要的朋友赶紧收藏。备份的必要性再生产环境中,为了防止硬件故...

光口路由器怎么重新设置(重置路由器的详细步骤)

路由器第一步:连好宽带(记住宽带账号和密码),备好路由器。第二步:网线连接光猫和路由器的WAN口,网线连接路由器数字口和电脑,接通电源。新路由器:打开浏览器,输...

公园摆地摊适合卖什么,四个暴利产品告诉你

昨天的文章让我太高兴了,5000多浏览量,40多个留言,有几个是广告我就删除了,400多个点赞,哈哈,值得高兴。昨天下午我把一些摊友拉进了一个群,除了发了505...

冲牙器什么牌子好(3款质量最好的便携式冲牙器)

冲牙器是一种必不可少的家庭卫生用品,是既舒服又管用的牙齿口腔清洁保健用品,下面小编为大家介绍便携冲牙器什么牌子好?推荐几款好用的便携冲牙器。松下(Panason...

传真号码格式怎么填写(企业传真号码查询)

不知不觉之中春节假期的“余额”已为零,又到了上班的时间。有的人在年前辞职现在要重新开始找工作或者刚刚准备出来工作。刚刚步入新职场的你,公司如果需要你去使用传真机...

u盘质量排名前十的有哪些,照着这些清单买准没错

随着科技的发展,u盘也随之普及普及,当前U盘市场的空前火爆,面对品牌众多、功能各异的U盘产品,u盘什么牌子好呢?我们今天就来看一下吧。u盘什么牌子好?没有最好,...

什么是k12教育体系,k12教育四大品牌介绍

K12在中国指小学6年、初中3年和高中3年共计12年的中小学基础教育阶段。从受众主题角度来讲,K12教育主要面临学生和家长两类人群,其中,当下K12教育的家长队...