java.util.Arrays的BUG - 二分搜索算法

转载 2006年06月06日 23:20:00
Joshua Bloch, 获得过Jolt最畅销奖的《Effective Java》的作者, 是Sun Microsystems的杰出工程师和Transarc的资深系统设计师, J2SE 5.0 Tiger的代言人和领路人, 也是还是JSR166的发起人之一..

后来, Joshua Bloch去了Google, 成为了Google的首席工程师

Joshua Bloch拥有卡耐基.梅隆大学(CMU)计算机科学的博士学位。

在最近Joshua Bloch的一篇文章里, Joshua Bloch回忆了当年在CMU上课的时候, vividly Jon Bentley 第一节算法课, 就要求所有刚进来的PHD学生, 每人都写一个二分查找算法. 然后发现, 多数人的算法都存在BUG, 这在当时给了Joshua Bloch 一个很深的印象..

在之后, Joshua Bloch 负责java.util.Arrays 代码编写的时候, 采用了Bentley 在<<Programming Pearls >>一书中的二分查找算法, 结果在8年后的今天, Joshua Bloch 发现, 这里面原来还是有一个BUG.

问题到底是出在哪里? 竟然逃过了Bentley 和Joshua Bloch 的双重检测?

一起来看看java.util.Arrays的代码:

1:     public static int binarySearch(int[] a, int key) {
2:         int low = 0;
3:         int high = a.length - 1;
4:
5:         while (low <= high) {
6:             int mid = (low + high) / 2;
7:             int midVal = a[mid];
8:
9:             if (midVal < key)
10:                 low = mid + 1;
11:             else if (midVal > key)
12:                 high = mid - 1;
13:             else
14:                 return mid; // key found
15:         }
16:         return -(low + 1);  // key not found.
17:     }


这是很经典的一个二分查找算法.

bug出现在第6行:

6:             int mid =(low + high) / 2;

在一般情况下, 这个语句是不会出错的, 但是, 当low+high的值超过了最大的正int值 (231- 1) 的时候, mid会变成负值,  这个时候, 会抛出ArrayIndexOutOfBoundsException 异常..


所以当一个数组包含超过2的30次方 个元素的时候, 就很可能会带来问题... 当然, 在一般的应用里面, 很少数组会包含那么多元素, 但是现在这样的情况已经越来越多了, 比如Google的海量运算..

那如何解决这个问题?

很简单, 修改这行语句为:

6:             int mid = low + ((high - low) / 2);
或者
6:             int mid = (low + high) >>> 1;


在c或者c++中, 则可以如下实现:
6:             mid = ((unsigned) (low + high)) >> 1;


这个问题告诉我们, 无论什么时候, 我们都不要想当然我们的程序是完美的. 我们需要细心的设计,测试再测试,符合规范的方法等等...对此, 你有什么经验和大家分享吗?

同样给我们带来的思考是: 8年了, java.util.Arrays 竟然存在这样一个bug, 这不得不让我们对JDK本身的测试性, 稳定性 怀有疑问.. 将来又会有多少个类似的bug出现呢?

java.util.Arrays的BUG - 二分搜索算法

Joshua Bloch, 获得过Jolt最畅销奖的《Effective Java》的作者, 是Sun Microsystems的杰出工程师和Transarc的资深系统设计师, J2SE 5.0 Ti...
  • longing_chen
  • longing_chen
  • 2006年06月10日 09:20
  • 895

[转贴]java.util.Arrays的BUG - 二分搜索算法

Joshua Bloch, 获得过Jolt最畅销奖的《Effective Java》的作者, 是Sun Microsystems的杰出工程师和Transarc的资深系统设计师, J2SE 5.0 Ti...
  • PeterHertz
  • PeterHertz
  • 2006年06月10日 14:18
  • 751

c语言实现二分搜索算法

二分搜索针对有序的数组,每次和中间元素比较,如果相等则直接返回,如果不相等则搜索范围可以减半。二分法可以将复杂度从 Ο(n) 降到 Ο(log n)。 本来以为二分法很简单,半分钟搞定,但写起来尼玛才...
  • zdarks
  • zdarks
  • 2015年07月22日 00:14
  • 3131

iOS开发中使用算法之二分搜索算法

本人是一名iOS开发程序猿,说实话在之前的开发项目中并没有到多少算法,算法对于本人也可以说是个硬伤。最近在找工作,面试官就会提到一些算法,由于不常用算法也就很难很好地回答面试的问题。由于之前学习过C以...
  • u010105969
  • u010105969
  • 2017年04月03日 21:11
  • 491

递归与分治策略之二分搜索算法

二分搜索算法是运用分治策略的典型例子 二分搜索算法充分利用了元素之间的次序关系(二分搜索的算法是基于有序列)采用分治策略,可在最坏情况下用O(logn)时间完成搜索任务。 二分搜索算法的基本思想是...
  • zhouyayong09
  • zhouyayong09
  • 2012年11月04日 09:05
  • 920

分治算法--二分搜索

二分查找:以有序表表示静态查找表时,查找函数可以用二分查找(binary search or half-intervalsearch )来实现。这种算法基于分治。...
  • ling_xiao007
  • ling_xiao007
  • 2015年08月03日 14:24
  • 1047

二分查找算法(Java)

今天在公司闲着蛋疼,网上瞎逛,偶然在InfoQ网站上看到一篇文章《计算机科学中最重要的32个算法》,原文地址:http://www.infoq.com/cn/news/2012/08/32-most-...
  • jackiehff
  • jackiehff
  • 2013年12月28日 14:42
  • 5053

【常用算法思路分析系列】与二分搜索相关高频题

本文是【常用算法思路分析系列】的第五篇,总结二分搜索相关的高频题目和解题思路。本文分析如下几个问题:1、求数组局部最小值问题;2、元素最左出现的位置;3、循环有序数组求最小值;4、最左原位;5、完全二...
  • shakespeare001
  • shakespeare001
  • 2016年06月12日 16:36
  • 2865

经典算法之二分搜索技术

二分法是个非常经典的算法,是分治思想的很好的体现。在复习算法的过程中,正好把他记录下来。本来想写递归的,后来想想还是用迭代,效率更高些,虽然对这种小的数据没什么多大影响,(好吧,其实是我太懒了 !!)...
  • zhyh1435589631
  • zhyh1435589631
  • 2015年06月06日 11:47
  • 1327

C++实现二分查找算法

想必二分查找很多人都不陌生,或许说很熟悉,但是在实际生活中又有很多人不能正确的写出它的相应代码,因为二分查找的边界条件等很难控制,下面我们来仔细的分析一下二分查找,这只是个人看法,如有异议,欢迎提出。...
  • Silence723
  • Silence723
  • 2016年07月27日 11:08
  • 3328
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:java.util.Arrays的BUG - 二分搜索算法
举报原因:
原因补充:

(最多只允许输入30个字)