>>分享孙卫琴的Java技术专稿和著作 书籍支持  卫琴直播  品书摘要  在线测试  资源下载  联系我们
发表一个新主题 开启一个新投票 回复文章 您是本文章第 10602 个阅读者 刷新本主题
 * 贴子主题:  【Java基础编程专题】浮点数的格式化以及运算精度 回复文章 点赞(0)  收藏  
作者:sunweiqin    发表时间:2022-03-15 19:09:17     消息  查看  搜索  好友  邮件  复制  引用

本文参考:
《Java面向对象编程》,作者:孙卫琴
《漫画Java编程》,作者:孙卫琴,杜聚宾

网络书店需要处理所出售的各种书籍的信息。下面是一个网络书店展示卫琴姐创作的一本书的信息。

书名: 精通Spring:Java Web开发技术详解
定价: 89.9
作者: 孙卫琴
出版社: 清华大学出版社
ISBN: 9787302588337
出版时间: 2021年11月11日
页数: 392
是否在售: 是

Book类表示一本书,它具有name属性(书名)、price属性(价格)、author属性(作者)、publisher属性(出版社)、isbn属性(ISBN编号)、publishDate属性(出版日期)、pages属性(页数)、amount属性(销售总金额)。还有一个isSale属性,表示书是否正在出售,取值为true,表示正在出售,取值为false,表示停止出售。

Book类有一个用于销售当前书籍的sale(int quantity)方法:
public void sale(int quantity){  //参数quantity表示销售数量
  // 符号* 是乘法运算符
  amount=amount+ price * quantity ;   //累计书的销售总金额
}

在Book类的程序入口main()方法中,创建一个表示上图所示的书的Book对象,再出售本书10000册,最后打印该书的书名和销售总金额。

为变量设定合理的数据类型

Book类有多个属性,它们属于不同的数据类型。例如name属性为String类型,price属性和amount属性为double类型,pages属性为int类型,isSale属性为boolean类型,publishDate属性为java.util.Date类型。
在本范例中,sale(int quantity)方法会改变Book对象的amount属性的取值,这体现了Java对象的属性和方法的关系:属性表示对象的数据,而方法可以操纵对象的数据。


import java.util.Date;
import java.text.SimpleDateFormat;
public class Book{
  String name;                             //表示书名
  double price;                            //表示价格
  String author;                           //书的作者
  String publisher;                       //表示出版社
  String isbn;                               //表示书的ISBN编号
  Date publishDate;                    //表示出版日期
  int pages;                                 //表示书的页数
  boolean isSale;                         //表示书是否正在出售
  double amount;                       //表示书的销售总金额
  ……  
  public void sale(int quantity){ //参数quantity表示销售数量
    amount=amount+ price* quantity ;   //累计书的销售总金额
  }

  public static void main(String args[])throws Exception{
    Book book=new Book();  
    book.name="精通Spring: Java Web开发技术详解";
    book.price=89.9;
    book.author="孙卫琴";
    book.publisher="清华大学出版社";
    book.isbn="9787302588337";
    book.pages=392;
    book.isSale=true;
    book.amount=0;

    SimpleDateFormat df =
                        new SimpleDateFormat("yyyy-MM-dd");

    //根据指定的日期格式返回一个表示2021年11月1日的Date对象
    Date publishDate = df.parse("2021-11-01");
    book.publishDate=publishDate;

    book.sale(10000); //销售10000册书
    System.out.println(book.name
          +"的销售总金额:"+book.amount) ;
  }    
}

Book类引用了java.util.Date类和java.text.SimpleDateFormat类,因此需要通过import语句将这两个类引入。

创建表示日期的Date对象

在Book类的main()方法中,以下代码创建了一个表示2021年11月1日的Date对象:


//指定日期格式
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");

//根据指定的日期格式返回一个表示2021年11月1日的Date对象
Date publishDate = df.parse("2021-11-01");

以上代码首先创建了一个表示具体日期格式“yyyy-MM-dd”的SimpleDateFormat对象,接下来调用这个对象的parse()方法,对字符串“2021-11-01”进行解析,把它转换为表示日期的Date对象。

格式化输出浮点数

在打印浮点类型数据时,如果希望只保留两位小数,可以利用String类的静态format(String fmt, Object... args)方法来设定数据格式,第一个参数fmt指定数据格式,第二个参数args指定待格式化的数据。
在以下代码中,format()方法的第一个参数“%.2f”指定数据格式,表示保留两位小数,第二个参数book.amount就是需要进行格式化的数据:

//保留总金额的两位小数
String amountDisplay=String.format("%.2f",book.amount);

System.out.println(book.name
           +"的销售总金额:"+amountDisplay) ;

假定book.ammout的取值为15600.983,那么amountDisplay变量的值为“15600.98”。

浮点数的运算精度

在Book类中,price变量和amount变量是double类型。值得注意的是,如果对这种变量进行数学运算,不能保证得到精确的运算结果。例如在以下代码中,price变量表示一本书的单价,quanity变量表示销售册数,表达式“price*quantity”把这两个变量相乘,计算销售总额:


double price =4.015;   //书的单价
int quantity=100;   //销售数量

//打印401.49999999999994
System.out.println(price*quantity);  

表达式“price*quantity”的运算结果为401.49999999999994,而不是预期的401.5。为什么会得到不精确的运算结果呢?这是因为在内存中,只能用二进制数据来表示各种类型的数据,例如用“00000011”来表示byte类型的数据3,用“00000000 00000000 00000000 00000011”表示int类型的数据3。那么,double类型的数据4.015在内存中如何表示呢?在内存中是采用二进制的科学计数法来表示小数的,这种方式无法精确地表示每个小数,只能提供一个非常接近小数的数值。当double类型的数据参与加减乘除这样的数学运算时,就可能导致不精确的运算结果。

在金融领域和商业领域,要求数学运算具有可靠的精确性,该如何实现呢?可以使用Java类库中的java.math.BigDecimal类。BigDecimal类支持对浮点数进行精确的数学运算。BigDecimal类包括以下方法:

add(BigDecimal b):进行精确的加法运算。
subtract(BigDecimal b) :进行精确的减法运算。
multiply(BigDecimal b) :进行精确的乘法运算。
divide(BigDecimal b, int scale,RoundingMode more) :进行除法运算,参数scale指定需要精确到小数点以后几位。参数mode
指定小数部分的舍入模式,如果取值为BigDecimal.ROUND_HALF_UP,表示采用四舍五入模式。

以下代码利用BigDecimal类来计算销售总额,得到了预期精度的运算结果:

double price =4.015;   //书的单价
int quantity=100;   //销售数量

//创建表示单价的BigDecimal对象
BigDecimal priceBig =
            new BigDecimal(Double.toString(price));

//创建表示销售数量的BigDecimal对象
BigDecimal quantityBig =
            new BigDecimal(Double.toString(quantity));

//进行乘法运算
BigDecimal amountBig=priceBig.multiply(quantityBig);

//获得BigDecimal对象包装的double类型数据
double amount=amountBig.doubleValue();

System.out.println(amount);    //打印401.5

程序猿的技术大观园:www.javathinker.net
  Java面向对象编程-->图形用户界面(上)
  JavaWeb开发-->JSP中使用JavaBean(Ⅰ)
  JSP与Hibernate开发-->映射对象标识符
  Java网络编程-->XML数据处理
  精通Spring-->Vue组件开发基础
  Vue3开发-->Vue指令
  【Vue.js技术专题】注册全局组件和局部组件
  【Vue.js技术专题】路由管理器的基本用法
  【Spring Cloud Alibaba专题】@SentinelResource注解的用法
  【Spring Cloud Alibaba专题】Nacos集群的Raft算法
  【Spring专题】把Model的数据存放在session范围
  【Spring专题】@Query注解设定查询语句
  探讨IT技术作者的素养
  从《精通Spring》和《精通Vue.js》的写作分享学习新技术的经...
  【持久化专题】对象-关系的映射概念
  【Java编程基础专题】用Scanner类读取用户在控制台输入的数据
  【JavaWeb专题】在JavaWeb应用中对客户请求的异步处理
  【JavaWeb专题】在Servlet中利用Apache开源类库实现文件上传
  【JavaWeb专题】选择32位或64位JDK或者Apache HTTP服务器的安...
  【Java基础编程专题】Java继承的利弊和使用原则
  【Java基础编程专题】为什么说:继承关系最大的弱点就是打破...
  更多...
 IPIP: 已设置保密
树形列表:   
1页 0条记录 当前第1
发表一个新主题 开启一个新投票 回复文章


中文版权所有: JavaThinker技术网站 Copyright 2016-2026 沪ICP备16029593号-2
荟萃Java程序员智慧的结晶,分享交流Java前沿技术。  联系我们
如有技术文章涉及侵权,请与本站管理员联系。