总览

错误表示错误和算术舍入错误有两种类型,它们在浮点计算中很常见。 在此简单示例中,这两个错误组合在一起,在Java 6中Math.round(0.4999999999999999999917)舍入为1。

表示错误

浮点数是以2为底的格式,表示所有数字都表示为2的幂的和。例如6.25是2 ^ 2 + 2 ^ 1 + 2 ^ -2。 但是,即使像0.1这样的简单数字也无法准确表示。 转换为BigDecimal时,这一点变得很明显,因为它将保留实际表示的值而无需取整。

new BigDecimal(0.1)= 0.1000000000000000055511151231257827021181583404541015625
BigDecimal.valueOf(0.1)= 0.1

使用构造函数获取实际表示的值,使用valueOf给出与打印 精度字相同的舍入值

解析数字时,会将其舍入为最接近的表示值。 这意味着存在一个略小于0.5的数字,由于它是最接近的表示值,因此将四舍五入为0.5。

下面用蛮力搜索舍入为1.0的最小值

public static final BigDecimal TWO = BigDecimal.valueOf(2);public static void main(String... args) {int digits = 80;BigDecimal low = BigDecimal.ZERO;BigDecimal high = BigDecimal.ONE;for (int i = 0; i <= 10 * digits / 3; i++) {BigDecimal mid = low.add(high).divide(TWO, digits, RoundingMode.HALF_UP);if (mid.equals(low) || mid.equals(high))break;if (Math.round(Double.parseDouble(mid.toString())) > 0)high = mid;elselow = mid;}System.out.println("Math.round(" + low + ") is " + Math.round(Double.parseDouble(low.toString())));System.out.println("Math.round(" + high + ") is " + Math.round(Double.parseDouble(high.toString())));
}

源代码

在Java 7上,您得到以下结果。

Math.round(0.49999999999999997224442438437108648940920829772949218749999999999999999999999999) is 0
Math.round(0.49999999999999997224442438437108648940920829772949218750000000000000000000000000) is 1

令人惊讶的是,在Java 6中,您获得了关注。

Math.round(0.49999999999999991673327315311325946822762489318847656250000000000000000000000000) is 0
Math.round(0.49999999999999991673327315311325946822762489318847656250000000000000000000000001) is 1

这些数字从何而来?

Java 7值是0.5和前一个表示值之间的中点。 高于此中点时,解析时该值将舍入为0.5。

Java 6值是0.5之前的值与其之前的值之间的中点。

Value 0.5 is 0.5
The previous value is 0.499999999999999944488848768742172978818416595458984375
... and the previous is 0.49999999999999988897769753748434595763683319091796875The mid point between 0.5and 0.499999999999999944488848768742172978818416595458984375is 0.4999999999999999722444243843710864894092082977294921875... and the mid point between 0.499999999999999944488848768742172978818416595458984375and 0.49999999999999988897769753748434595763683319091796875is 0.4999999999999999167332731531132594682276248931884765625

为什么Java 6的值更小

在Java 6 Javadoc中, Math.round(double)被定义为

(long)Math.floor(a + 0.5d)

此定义的问题在于0.49999999999999994 + 0.5的舍入误差为1.0。

在Java 7 Javadoc Math.round(double)中,它仅声明:

返回最接近参数的长整数,并舍入四舍五入。

那么Java 7如何解决这个问题?

Java 7的Math.round的源代码如下所示

public static long round(double a) {if (a != 0x1.fffffffffffffp-2) // greatest double value less than 0.5return (long)floor(a + 0.5d);elsereturn 0;
}

最大值小于0.5的结果将进行硬编码。

那么0x1.fffffffffffffp-2是什么呢?

它是浮点值的十六进制表示。 它很少使用,但是它很精确,因为所有值都可以无错误地表示(最多53位)。

相关链接

错误ID:6430675 Math.round对于0x1.fffffffffffffpp-2具有令人惊讶的行为
为什么Math.round(0.49999999999999994)返回1

参考: 为什么在Java 6上 ,我们的JCG合作伙伴 Peter Lawrey在Vanilla Java博客上将Math.round(0.499999999999999917)舍入为1 。

翻译自: https://www.javacodegeeks.com/2012/04/why-mathround0499999999999999917-rounds.html

为什么在Java 6上Math.round(0.499999999999999917)舍入为1相关推荐

  1. 5 在java等于多少,java基础面试题之Java中的Math. round(-1. 5)等于多少

    Java 中的 Math. round(-1. 5) 等于多少? 答案:-1 /** * Returns the closest {@code long} to the argument, with ...

  2. java 中的 Math.round(-1.5) 等于多少?

    面试题汇总 java 中的 Math.round(-1.5) 等于多少? 这道题目的答案是 -1. 其实这道题目考察的主要知识点就是:Math.round方法的概念以及返回值类型. 注意:Math的r ...

  3. java ftp上传文件0字节_FTP上传无文件以及0字节问题

    这几天在做一个FTP上传文件的功能,在本地运行完全没有问题,上传文件成功,图片成功显示.在公网(centos系统)上进行测试的时候就出了问题了,上传一直卡到storeFile上,一般是会卡住30-60 ...

  4. java math round小数_Java——Math的round方法

    代码如下,后面的注释是输出的结果 public static voidmain(String[] args) { System.out.println(Math.round(0.399));//0 S ...

  5. Java史上最全的面试题汇总(JVM/Mysql/boot/cloud/zk/kafka/MQ/redis)

    文章目录 Java 基础 1. JDK 和 JRE 有什么区别? 2. == 和 equals 的区别是什么? 3. 两个对象的 hashCode()相同,则 equals()也一定为 true,对吗 ...

  6. Math.round(),Math.ceil(),Math.floor()的区别

    round() 方法可把一个数字舍入为最接近的整数. 就是基本的四舍五入 document.write(Math.round(0.49)) 结果为:0document.write(Math.round ...

  7. C#中Math.Round()实现中国式四舍五入

    原文:C#中Math.Round()实现中国式四舍五入 C#中Math.Round()实现中国式四舍五入 C#中的Math.Round()并不是使用的"四舍五入"法.其实在VB.V ...

  8. C#取整函数Math.Round、Math.Ceiling和Math.Floor

    1.Math.Round:四舍六入五取偶 引用内容 Math.Round(0.0) //0 Math.Round(0.1) //0 Math.Round(0.2) //0 Math.Round(0.3 ...

  9. C#取整函数Math.Round、Math.Ceiling和Math.Floor 【非原创,用来收藏,分享】

    1.Math.Round:四舍六入五取偶 引用内容 Math.Round(0.0) //0 Math.Round(0.1) //0 Math.Round(0.2) //0 Math.Round(0.3 ...

最新文章

  1. 网络营销专员表示网络营销中设置不当会影响蜘蛛爬虫对网站抓取
  2. 80客团队博客建设的思路
  3. mozjpeg:JPEG图片压缩5%,获Facebook支持
  4. 关于flex,好像有12个属性非常重要
  5. Redis常见问题及其一些重点知识总结
  6. Wireshark个人实战总结
  7. [转载] Python面向对象编程系列第一篇
  8. Multisim软件实验
  9. 单片机原理及应用姜志海pdf_单片机原理及应用.pdf
  10. pc临时调起QQ临时会话
  11. eNSP综合实验——简易园区网的搭建
  12. Android Studio 录屏/电脑实时显示手机的画面
  13. javascript 模拟退格键_js按钮模拟键盘退格键定位删除问题
  14. 《奇特的一生:柳比歇夫坚持56年的时间统计法》的读书笔记(作者: 【俄】格拉宁)
  15. AndroidTV语音搜索
  16. pdf文件怎么转化为word,pdf转换成word的方法
  17. git clone出现fatal: unable to checkout working tree报错的解决办法
  18. 测试最常见的21个故障模型
  19. Flink教程(16)- Flink Table与SQL
  20. ansible基础-task控制

热门文章

  1. ibatis(2)ibatis是什么
  2. spock 集成测试_使用Spock 1.2简化对遗留应用程序的集成测试
  3. java ee 8 api_Java EE 8安全性API:概述
  4. 通过Java和Spring Boot应用程序将Gmail用作SMTP服务器
  5. threadsafe_Agrona的Threadsafe堆缓冲区
  6. jstack调试_增压的jstack:如何以100mph的速度调试服务器
  7. gc 吞吐量和停顿时间_GC对吞吐量和延迟的影响
  8. 自定义jackson序列化_Jackson中的自定义反序列化程序和验证
  9. ubuntu生成密钥和证书_基于浏览器的密钥生成以及与浏览器的密钥/证书存储的交互...
  10. 棋牌类游戏算法–牌分类_快速分类–三向和双枢轴