自從看了cnblog上那篇講「野生」程序員的文章,我也時常反思做爲科班出身的本身,是否是還帶着一些「野生」的作派。咱們每每80%的時間在作一些純業務的事情上,而每每百分之90的時間裏面咱們的業務量不足夠大到須要考慮性能的地步。天天重複地活着,有什麼意義呢?php
因此經常有人說,算法和數據結構,設計模式,都是並無什麼卵用。我一直對這種觀點很反感,計算機編程是 一門科學,科學在於高效。若是咱們不考慮大流量、高併發,咱們能夠很任性地寫任何功能,大不了加載緩慢。咱們忽略那些看似不重要,或者用不上的黑科技,覺得一直呆在地球表面上是最安全的。java
我在知乎裏面寫過一個回覆:我見過十年的碼畜,也見過一年成架構的神人。之因此有的人用一年走完別人十年走不完的技術道路,是由於關注代碼和業務背後的細節,不斷積累迭代。最近在看《代碼之美》這本書,有些感觸。我用一個最不被你們重視的算法爲例:程序員
二分法查找。算法
我對這個算法記憶猶新,大一的時候曹海老師在紙上給我推演了其中過程。我用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)
.-' _..`. / .'_.'.' | .' (.)`. ;' ,_ `. .--.__________.' ; `.;-'| ./ /| | / `..'`-._ _____, ..' / | | | |\ \ / /| | | | \ \ / / | | | | \ \ /_/ |_| |_| \_\ |__\ |__\ |__\ |__\