zoukankan      html  css  js  c++  java
  • 不容小视的算法

    自从看了cnblog上那篇讲“野生”程序员的文章,我也时常反思作为科班出身的自己,是不是还带着一些“野生”的做派。我们往往80%的时间在做一些纯业务的事情上,而往往百分之90的时间里面我们的业务量不足够大到需要考虑性能的地步。每天重复地活着,有什么意义呢?

    所以常常有人说,算法和数据结构,设计模式,都是并没有什么卵用。我一直对这种观点很反感,计算机编程是 一门科学,科学在于高效。如果我们不考虑大流量、高并发,我们可以很任性地写任何功能,大不了加载缓慢。我们忽略那些看似不重要,或者用不上的黑科技,以为一直呆在地球表面上是最安全的。

    我在知乎里面写过一个回复:我见过十年的码畜,也见过一年成架构的神人。之所以有的人用一年走完别人十年走不完的技术道路,是因为关注代码和业务背后的细节,不断积累迭代。最近在看《代码之美》这本书,有些感触。我用一个最不被大家重视的算法为例:

    二分法查找。

    我对这个算法记忆犹新,大一的时候曹海老师在纸上给我推演了其中过程。我用java代码实现如下:

    public class TestBinary {
        /**
         * 二分法查询
         * 
         * @param arr
         * @param value
         * @return
         */
        public static int binary(int[] arr, int value) {
            if (arr.length <= 0) System.out.println("no array to search");
            int low = 0;// 低位
            int high = arr.length -1; //高位
            if (low <= high) {
                int mid = (low + high) /2;
                if (arr[mid] == value) return mid;
                if (arr[mid] > value) {
                    high = mid - 1;
                }
                if (arr[mid] > value) {
                    low = mid + 1;
                }
            }
            return -1;
        }
    
        /**
         * @param args
         */
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            int[] a = {1, 2, 9, 33, 43, 52};
            int value = binary(a, 9);
            System.out.println(value);
        }
    
    }

    这是最常规的写法,看上去也没什么问题。但是如果我们要查找的数组变得越来越大,就会出现性能和整型溢出的问题。先说性能吧,其中int mid = (low+high)/2;这句在循环中,不断地在栈上分配临时变量,这也是一种消耗,可以把它写在循环外。溢出问题也是在这句,如果high变量(也就是数组长度)足够大,超过32位机器的2^31 -1的局限,或者64位机的整型极限,那么就会溢出为负数。有人建议写成:

    mid = (low + high) >>> 1; 

    用位运算来防止整型溢出。对位运算不太熟悉的童鞋可以去看看相关资料。

    很多人看到这里就感觉皆大欢喜的happy ending,但是我还不想就这么草率地结束。

    这里面就存在一个悖论,java不能造出一个大于最大整型数值长度的数组,那么我该如何检验这个溢出问题呢。而且凭什么说用>>> 1就可以解决。我freephp第一个不服!

    如果一直纠结造出数组来验证,那么就走不通了。所以我们换个思路,其实本质就是很大的两个数相加除2或用位运算会不会整型溢出的测试。代码如下:

    System.out.println("除以2:"+ ((1000000000+Integer.MAX_VALUE) /2));

    System.out.println("除以2:"+ ((1000000000+Integer.MAX_VALUE) >>> 1));

    输出结果为:

    除以2:-573741824

    除以2:1573741823

    可见位运算可以保证整型不溢出。

    (待续ing)


                       .-' _..`.                  /  .'_.'.'                 | .' (.)`.                 ;'   ,_   `. .--.__________.'    ;  `.;-'|  ./               /|  |               / `..'`-._  _____, ..'     / | |     | |     / /| |     | |    / / | |     | |     /_/  |_|     |_|   \_ |__  |__    |__  |__

  • 相关阅读:
    nginx 转发请求头信息
    canny算法实现
    单字符旋转校正
    图像匹配
    Edge Extraction (subpixel Precise)
    Edge Extraction 边缘提取
    圆形环绕字 从直角坐标到极坐标的转换
    Image acquisition
    Contour Processing
    Matching
  • 原文地址:https://www.cnblogs.com/freephp/p/4969374.html
Copyright © 2011-2022 走看看