标签:character 源码 编译原理 慢慢 blog static 为什么 写代码 ber
今天不看spring了,上了一天的课,晚上还要写编译原理作业(头疼)。先看点api的源码放松一下。不得不说,看这些世界上最顶尖的程序员写出来的东西真是和看nba一样是一件愉快的事情,虽然有点烧脑。
先看看Integer.toString(int i)是怎么实现的。
首先有两个相关的方法,stringSize(int x)和getChars(int i, int index, char[] buf).
1 final static int [] sizeTable = {9,99,999,9999,99999,999999,9999999,99999999,999999999,Integer.MAX_VALUE}; 2 static int stringSize(int x) { 3 for(int i=0; ;i++) 4 if(x<= sizeTable[i]) 5 return i+1; 6 }
原来确定一个数字的位数是这么玩的,简直厉害哭了;突然想起自己以前的不断除10,简直脸红。忍不住临摹了一遍。
1 static void getChars(int i, int index, char[] buf) { 2 int q,r; 3 int charPos = index; 4 char sign =0; 5 if(i < 0) { 6 sign = ‘-‘; 7 i = -1; 8 } 9 while(i >= 65536) { 10 q = i/100; 11 r = i-((q << 6) + (q << 5) +(q << 2); 12 i=q; 13 buf [--charPos] = DigitOnes[r]; 14 buf [--charPos] = DigitTens[r]; 15 } 16
继续临摹,话说代码到这边我还是可以接受的,每次取头两位数转换成char放进buf数组。但是我看到后面的一段我简直要崩溃了。。这是何等的卧槽,为什么能把代码写得这么优雅。。。
//Fall thru to fast mode for smaler numbers //assert(i <=65536, i); for(; ;) { q = (i *52429)>>> (16+3); r = i - (( q << 3) + (q << 1));//r = i-(q*10); buf[--charPos] = digits [r]; i = q; if (i == 0)break; } if(sign != 0) { buf [--charPos] = sign; } }
简直帅炸了好不好,终于知道为什么前面要用65536分界了。因为65536*52429会越界。q = (i*52429)>>>(16+3)相当于i*52429/524288。52429/524288=0.1000004.这真他妈是把程序的速度提升到了极致。写代码居然是一件这么有趣的事。捂脸.jpg。
1 public static String toString(int i) { 2 if (i == Integer.MIN_VALUE) 3 return "-2147483648"; 4 int size = (i<0)? stringSize(-i) + 1 : stringSize(i); 5 char[] buf = new char[size]; 6 getChars(i, size ,buf); 7 return new String(buf, true); 8 }
toString本身倒是很好理解,第一个if主要是因为int负数的范围比正数大一,不当特例列出来,判断数组位数会有困难。下面一句负数的时候位数加一是因为负数有符号-。
讲道理今天还看了一个parseInt的实现,主要通过调用Character.digit().要写作业了,懒得写了。未完待续,慢慢补完全部。。。
标签:character 源码 编译原理 慢慢 blog static 为什么 写代码 ber
原文地址:http://www.cnblogs.com/wkmocr/p/7608107.html