常见的舍入方式

四舍五入

我们在学习计算机科学之前,以及日常生活中,用的是四舍五入。
所谓四舍五入,就是取4即归0,取5即归1,这个问题与我们需要的精度有关。
在计算机科学中一般用round() 表示四舍五入。

比如0.499999,这是一个六位小数,我们想要四舍五入,就要看精度。
精确到1,结果是0
精确到0.1.结果是0.5
精确到0.01,结果是0.50
……

向上取整

向上取整是一种无视四舍五入的行为,在计算机科学中应用广泛,意为取大于等于该数值的最小整数。
符号⌈⌉,英文Ceiling,通常写作ceil()
英语中,ceil 的一个意思是 “天花板”,这样我们就不难理解了。
ceil()一般应用于浮点数,如果不是浮点的话,本就是整数,有什么取整的必要呢?

比如0.499999,上整就是1
比如-0.499999,上整就是0

向下取整

向下取整是一种无视四舍五入的行为,在计算机科学中应用广泛,意为取小于等于该数值的最大整数。
符号⌊⌋,英文Floor,通常写作floor()
英语中,floor 的一个意思是 “地板”,这样我们就不难理解了。
不难发现,上整和下整是恰好相反的,所以也是应用于浮点的。

比如0.499999,下整就是0
比如-0.499999,下整就是-1

不难发现,⌈x⌉ - ⌊x⌋ = 1

截断取整

截断取整是一种无视四舍五入的行为,在计算机科学中应用广泛,意为取舍去小数点和小数点后所有数位的整数。

比如0.499999,截断取整就是0
比如-0.499999,截断取整也是0

向两端取整

向两端取整是一种无视四舍五入的行为,在计算机科学中应用广泛,意为取临近的∞方向的整数。

比如0.5,向两端取整就是1
比如-0.5,向两端取整就是-1

Math类中的舍入问题

主要有以下几种舍入方式:

  • ceil​(double a):作用是返回大于或等于参数且数值上等于整数的最小(最接近负无穷大)的浮点数
    返回double型
    解释的通俗点就是向上取整后转成数学上相等的double型
  • floor​(double a):作用是返回小于或等于参数且数值上等于整数的最大(最接近正无穷大)的浮点数
    返回double型
  • nextDown​(…d/f):作用是返回在负无穷大方向上与d/f相邻的浮点值
    参数可以是double d、float f两种,返回对应的类型
  • nextUp​(…d/f):作用是返回在正无穷大方向上与d/f相邻的浮点值
    参数可以是double d、float f两种,返回对应的类型
  • rint​(double a):作用是返回在数学上等于与参数值最接近且是整数的double
    返回double型
    解释的通俗一点就是四舍五入后取数学上相等的double型浮点
  • round​(…a):作用是返回参数四舍五入后的整数值
    参数可以是double、float两种
    double参数返回long,float参数返回int

nextDown()​、nextUp()​、rint​()​ 按照各自的规则舍入得浮点。
ceil​()​、floor()​​、round()​分别是前面提的,取整得整数,很常见。

除法的舍入问题

System.out.println(1/2);

结果是什么?

System.out.println(-1/2);

结果又是什么?

答案都是一样的:
0

为什么呢?
整数除整数,除号直接截断取整,正负号规则相同,相当于直接砍去小数点和小数点后数位。

Java不像Python还分/和//,只有/,那怎么能精确呢?
当然是转型为浮点啦:

System.out.println((double)1/2);

答案:
0.5

那浮点精确吗?

System.out.println(0.1+0.2);

结果是什么?

答案:
0.30000000000000004

为什么呢?
简而言之,double双精度浮点数,遵循IEEE754,64位,52位小数+11位指数+1位符号。
计算机没有分数,也没有十进制小数,所以只能用二进制小数表示,难免不精确。

用更精确的BigDecimal算一下:
0.3000000000000000166533453693773481063544750213623046875
只能说相对精确了很多,也不能说完全精确了,毕竟是计算机。

printf()的舍入问题

System.out.printf("%.0f", 0.5);

结果是什么?

System.out.printf("%.0f", -0.5);

结果又是什么?

答案分别是:
1
-1

可见printf()的浮点舍入方式是向两端取整。

double向float强转的舍入问题

我们都知道,double表示64位双精度浮点数,float代表32位单精度浮点数,double精确度高,也是默认的浮点数类型。

看下面的代码:

double a = 0.555555555;
float b = (float)a;

b的值是多少?

答案是:
0.5555556

而下面的情况呢?

double a = 0.55555554;
float b = (float)a;

b的值是:
0.5555555

可见printf()的浮点舍入方式是四舍五入。

BigDecimal处理舍入问题的八种方式

原先BigDecimal类舍入采取本类中属性值来定义,后被标定为 @Deprecated
新的方式被定义在枚举类 java.math.RoundingMode 中,有以下八种情况:

  • CEILING :向正无穷大舍入
  • DOWN :向零舍入
  • FLOOR :向负无穷大舍入
  • HALF_DOWN :向“最近的邻居”舍入,除非两个邻居都等距,在这种情况下,将向下舍入
  • HALF_EVEN :向“最近的邻居”舍入,除非两个邻居都等距,在这种情况下,将向相邻偶数舍入。
  • HALF_UP :向“最近的邻居”舍入,除非两个邻居都等距,在这种情况下,将向上舍入
  • UNNECESSARY :舍入模式可以断言所请求的操作具有准确的结果,因此不需要舍入
  • UP :舍入模式从零舍入(向着远离零的方向)

对此的理解可以参考上面的例子啦……

反思

虽说进行了整理,但我也有一个困惑:是不是我理解这个舍入问题还是站在了十进制的角度而计算机站在二进制的角度呢?这两种思维看待舍入问题会有哪些差别呢?
确实有点困惑,待我思索一下……有确定答案的读者还请留言,感谢……

【Java】深入探讨Java数值舍入问题相关推荐

  1. 深入探讨 Java 类加载器

    深入探讨 Java 类加载器 类加载器(class loader)是 Java™中的一个很重要的概念.类加载器负责加载 Java 类的字节代码到 Java 虚拟机中.本文首先详细介绍了 Java 类加 ...

  2. Java数组之一维数值数组之成绩统计

    Java数组之一维数值数组 Java数组之一维数值数组之成绩统计 一维数组 声明一维数值数组变量 创建一维数值数组 一维数组初始化 一维数组元素的使用 一维数组长度 成绩统计 Java数组之一维数值数 ...

  3. Java数组之一维数值数组之数据去重

    Java数组之一维数值数组之数据去重 去除数组中的重复数据 1.接收给定的数据(如:4 88 43 43 98 #-,其中第一个数代表数组长度,其余数代表数组元素,# 号用于终止接收数据,这些数据用空 ...

  4. [Java学习探讨]为什么学Java虚拟机的Java程序员更有价值?

    个人博客导航页(点击右侧链接即可打开个人博客):大牛带你入门技术栈 [Java学习探讨]为什么学Java虚拟机的Java程序员更值钱? 曾经的我经常害怕处理与JVM相关的异常,对JVM的配置参数也一无 ...

  5. Java数据类型划分(数值型、布尔型、字符型)

    1.Java数据类型分类 Java中数据类型一般分为两类: >基本数据类型:描述的一些具体的数字单元,例如1.1.1等: (1)数值型: >>整型:byte.short.int.lo ...

  6. 深入探讨 java.lang.ref 包--转

    概述 Java.lang.ref 是 Java 类库中比较特殊的一个包,它提供了与 Java 垃圾回收器密切相关的引用类.这些引用类对象可以指向其它对象,但它们不同于一般的引用,因为它们的存在并不防碍 ...

  7. 深入探讨 java.lang.ref 包

    http://www.ibm.com/developerworks/cn/java/j-lo-langref/ 概述 Java.lang.ref 是 Java 类库中比较特殊的一个包,它提供了与 Ja ...

  8. 深入探讨 Java 类加载器(一)

    2019独角兽企业重金招聘Python工程师标准>>> 类加载器是 Java 语言的一个创新,也是 Java 语言流行的重要原因之一.它使得 Java 类可以被动态加载到 Java ...

  9. java ref object_深入探讨 java.lang.ref 包

    概述 Java.lang.ref 是 Java 类库中比较特殊的一个包,它提供了与 Java 垃圾回收器密切相关的引用类.这些引用类对象可以指向其它对象,但它们不同于一般的引用,因为它们的存在并不防碍 ...

  10. 探讨 Java 中 valueOf 和 parseInt 的区别

    文章目录 前言 区别 parseInt valueOf 后记 前言 在编程中,遇到类型转换,好像会经常用到 parseInt 和 valueOf,当然这里只拿 Integer 类型进行陈述,其他类型也 ...

最新文章

  1. 1099 Build A Binary Search Tree
  2. 『TCP/IP详解——卷一:协议』读书笔记——03
  3. 关于ibatis.net 和 Nhibernate的选择
  4. LeetCode-46. Permutations
  5. bootstrap-表格-普通表格
  6. 打印机测试图_INTAMSYS高温PEEK 3D打印机助力智能组件创新制造
  7. 基于c#的相关性分析_不同区间衰退路径下锂离子电池的性能相关性及温度适用性分析...
  8. Ceilometer - Install the API behind mod_wsgi
  9. 190707每日一句,一堂重要的人生之课Let it go, 穷则变变则通
  10. VMware Tools详细步骤
  11. 互斥机制synchronized学习
  12. 初中数学知识点总结_初中数学知识点汇总大全【超详细】,初中数学知识点归纳公式大全...
  13. python制作时间,如何利用python制作时间戳转换工具详解
  14. 【stm32CubeMX】STM32F103c8t6串口通信
  15. Q版人物动作怎么画?如何画好Q版人物动作?
  16. 你还在靠“喂喂喂”来测语音通话质量吗,看完这篇文章你就能掌握正确姿势。
  17. 计算机Excel设置透视图,电脑Excel表格中数据透视图怎么制作
  18. 全栈工程师的百宝箱:黑魔法之文档篇
  19. 传奇世界私服务器端制作,关于内网架设传奇世界私服问题的一些解答
  20. 使用win10自带功能,横屏、竖屏显示器分别设置壁纸

热门文章

  1. Python 高级网络操作 - Python Advanced Network Operations
  2. Centos7 Yum安装 PHP5.5,5.6,7.0
  3. navicat premium 连接出现的问题
  4. YII2 实现后台操作记录日志
  5. WPF: 使用CommandManager.InvalidateRequerySuggested手动更新Command状态
  6. PHP出现 Notice: Undefined index:...的原因及解决办法
  7. oracle授权操作
  8. Build path -No action available/classpath .project
  9. Redis集群搭建使用
  10. i5 1135g7什么水平_i7-10510U和i5-1135G7对比,该怎么选择呢?