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

总览

错误表示错误和算术舍入错误有两种类型,它们在浮点计算中很常见。 在此简单示例中,这两个错误组合在一起,在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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/373137.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

单利模式

class Singleton{ public:static Singleton* GetInstance(){if (m_pInstance nullptr){m_pInstance new Singleton;}return m_pInstance;} private:Singleton(){}//需要将构造和析构定义成私有的防止外界构造和析构~Singleton(){}static Singleton* m_pInstance;//static所有…

C语言switch中break的作用,C语言中switch...case语句中break的重要性

在C语言中switch...case语句是经常用到的&#xff0c;下面我介绍一下在使用该语句时候需要注意的一个细节问题。话不多说&#xff0c;直接举例子&#xff1a;例子1&#xff1a;switch(fruit){case 1:printf("apple"); break;case 2:printf("banana"); brea…

BZOJ 1898: [Zjoi2005]Swamp 沼泽鳄鱼 [矩阵乘法]

1898: [Zjoi2005]Swamp 沼泽鳄鱼 Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 1082 Solved: 602[Submit][Status][Discuss]Description 潘塔纳尔沼泽地号称世界上最大的一块湿地&#xff0c;它地位于巴西中部马托格罗索州的南部地区。每当雨季来临&#xff0c;这里碧波荡漾…

从Spring开始,Java EE 6必须具备哪些附加功能?

我是一名高级Java开发人员&#xff0c;必须研究应用程序架构师选择的技术。 我最多只能表达对特定技术的看法&#xff0c;不能做出/影响技术选择的决定。 因此&#xff0c;在我的正式项目中&#xff0c;我别无选择从Spring迁移到JavaEE6或从JavaEE6迁移到Spring。 我坚信&#…

UML类图与类的关系详解

在画类图的时候&#xff0c;理清类和类之间的关系是重点。类的关系有泛化(Generalization)、实现&#xff08;Realization&#xff09;、依赖(Dependency)和关联(Association)。其中关联又分为一般关联关系和聚合关系(Aggregation)&#xff0c;合成关系(Composition)。下面我们…

教程:Hibernate,JPA和Spring MVC –第2部分

本教程将向您展示如何使用基本的Hibernate / JPA应用程序&#xff0c;如何将其转换为Spring MVC Web项目&#xff0c;以便能够在Web浏览器中查看数据库&#xff0c;以及最后使用Spring的Transactional注释来减少样板代码。 本教程假定您熟悉Java和Maven&#xff0c;并且已经完成…

算法转换c语言程序,(转)C语言实现卡尔曼滤波算法程序

非常感谢原作者&#xff0c;我在这个的基础上转换成纯整形运算。STM32F103 12位ADC先放大1000倍再运算&#xff0c;理论上可以保留小数点后三位的结果。效果非常不错&#xff0c;运算速度也快&#xff0c;72M时钟 1-2uS左右(根据MDK周期数)。]uint32_t KalmanFilter(int32_t Re…

Java 8的烹调方式–拼图项目

什么是Project Jigsaw&#xff1a;Project Jigsaw是使Java编译器模块知道的项目。 多年以来&#xff0c;Java API一直是整体的&#xff0c;即从代码的任何部分都可以平等地看到整个API。 还没有任何方法可以声明代码对任何其他用户库的依赖关系。 拼图项目试图以非常有效的方式…

python之路-SQLAlchemy

SQLAchemy SQLAlchemy是Python编程语言下的一款ORM框架&#xff0c;该框架建立在数据库API之上&#xff0c;使用关系对象映射进行数据库操作&#xff0c;简言之便是&#xff1a;将对象转换成SQL&#xff0c;然后使用数据API执行SQL并获取执行结果。 安装&#xff1a; pip3 inst…

POJ 1751 Highways

题意&#xff1a;n个城市&#xff0c;然后把n个城市的坐标都给你&#xff0c;然后给你m条已经修好的道路&#xff0c;然后给出m个已经修好道路的城市a&#xff0c;b&#xff0c; However, they want to guarantee that every town is highway-reachable from every other town.…

C语言编程中void什么意思,程序设计中遇到的void到底是什么意思

部分编程的初学者都会问"void是什么意思","为什么很多函数前都要加个void".实际上,void最简单的解释就是把0转换成空类型的意思。下面用各个开发语言来详解void1.C语言中的void表示空类型&#xff0c;它跟int&#xff0c;float是同地位的&#xff0c;一般用…

Linux中vim编辑器的缩进的功能键

vim编程时,经常需要对代码进行缩进处理,以增加程序的可读性和后期的代码维护. 可以采用多种方式达到缩进的目的: 1) 命令模式(command mode) 2) Visual模式&#xff08;visual mode&#xff09; 2) 输入模式(entry mode) 3) 末行模式(last-line mode) 4) 在/etc/vimrc有给予vim…

JSF 2,PrimeFaces 3,Spring 3和Hibernate 4集成项目

本文展示了如何集成JSF2&#xff0c;PrimeFaces3&#xff0c;Spring3和Hibernate4技术。 它为Java开发人员提供了一个通用的项目模板。 另外&#xff0c;如果Spring不用于业务和数据访问层&#xff0c;则可以提供JSF – PrimeFaces和Hibernate集成项目。 二手技术&#xff1a…

c语言编程文件中删除数据结构,C语言数据结构实战(一)顺序表的插入与删除

今天学习了思成老师的数据结构实战教程 写了一个顺序表 插入和删除的操作 把源码共享给大家 一共包括list.c stu.h main.c list.h .h文件是头文件 需要引入 具体的功能我都已经在代码中写明了list.h代码如下&#xff1a;//线性表的定义在头文件中实现#ifndef _LIST_H#define …

内存使用分析工具Valgrind简单用法

转载自 http://www.cnblogs.com/sunyubo/archive/2010/05/05/2282170.html 暂时还未使用过&#xff0c;记录下&#xff0c;记录下&#xff0c;记录下 Valgrind的主要作者Julian Seward刚获得了今年的Google-OReilly开源大奖之一──Best Tool Maker。让我们一起来看一下他的作品…

Lucene概述第一部分:创建索引

介绍 我最近一直在与开源搜索引擎Lucene合作 。 我不是专家&#xff0c;但是由于我只是浏览了一些相当稀疏的文档并将应用程序从Lucene的很旧的版本迁移到了最新版本的2.4&#xff0c;所以我在总体上很清楚。 Lucene的文档有点让人难以想象&#xff0c;因此我想趁此机会在我脑海…

初识openstack

一、 什么是openstack&#xff1f; OpenStack是一个由NASA&#xff08;美国国家航空航天局&#xff09;和Rackspace合作研发并发起的&#xff0c;以Apache许可证授权的自由软件和开放源代码项目。 二、openstack前世今身 openstack是一个跟Eucalyptus,AWS(Amazon web Service)类…

c语言case多语句的取值,Switch Case语句中多个值匹配同一个代码块的写法

C&num;&plus;JQuery&plus;&period;Ashx&plus;百度Echarts实现全国省市地图和饼状图动态数据图形报表的统计在目前的一个项目中,需要用到报表表现数据,这些数据有多个维度,需要同时表现出来,同时可能会有大量数据呈现的需求,经过几轮挑选,最终选择了百度的e…

php解决下单、抽奖并发导致的库存负数的问题

我们知道数据库处理sql是一条条处理的&#xff0c;假设购买商品的流程是这样的&#xff1a; sql1:查询商品库存 if(库存数量 > 0) { //生成订单... sql2:库存-1 } 当没有并发时&#xff0c;上面的流程看起来是如此完美&#xff0c;假设同时两个人下单&#xff0c;而…

在Spring中使用JDBCJobStore配置Quartz

我将开始一些有关Quartz Scheduler内部&#xff0c;提示和技巧的系列文章&#xff0c;这是第0章-如何配置持久性作业存储。 在Quartz中&#xff0c;您基本上可以在将作业和触发器存储在内存中以及在关系数据库中进行选择&#xff08; Terracotta是最近添加的混合功能&#xff0…