- toString()方法的学习
分析了java中将int转化为String的过程。其中的很多在时间效率方面的优化方法值得学习。
提示: (i * 52429) >>> (16+3) = (i * 52429) / 524288 约等于i * 0.1
其中stringSize()是用于求出转化后的string的长度的。为了提高效率,这个方法采用查表来获取到string的长度即几位数负数加1位,实现如下:
核心算法为getchar()中
从getChars的方法注释中可以看到,当i == Integer.MIN_VALUE 时,getChars方法会失效。这就是为什么toString(int i)的第一句要判断输入是否为整数的下界。(失效的原因在于getChars方法中会将负数转化为正数,而 Integer.MAX_VALUE = ( - Integer.MIN_VALUE ) - 1 ,所以当输入为Integer.MIN_VALUE时,化为正数的时候会溢出。)
当i>65536的时候通过i - ( i / 100* 100 )得到每一位的数值。
有才的地方:DigitOnes 和DigitTwos数组,通过除100得到的余数匹配来个数组中的值就可以得到想要的char类型的数值。
即然后分别查DigitTens和DigitOnes两个表,直接获取十位和个位。
当i < 65536时,通过i - ( i / 10 * 10 )来获得每一位。
这里的 q = (i * 52429) >>> (16+3)可能会让人费解,实际2 ^ 19 = 524288,而52429 / 524288 = 0.10000038146972656,约为0.1,所以这一步实际就是在除以10,只不过是换种效率更高的方法而已。
值得一提的是除了52429外,还有很多数可以选,如:
2^10=1024, 103/1024=0.1005859375
2^11=2048, 205/2048=0.10009765625
2^12=4096, 410/4096=0.10009765625
2^13=8192, 820/8192=0.10009765625
2^14=16384, 1639/16384=0.10003662109375
2^15=32768, 3277/32768=0.100006103515625
2^16=65536, 6554/65536=0.100006103515625
2^17=131072, 13108/131072=0.100006103515625
2^18=262144, 26215/262144=0.10000228881835938
2^19=524288, 52429/524288=0.10000038146972656
当然,选52429也不是偶然,而是因为它是是在不超出整形范围内,精度最高的一个
最后的就是看是否为负数,如果是负数的话,加入‘-’字符到buf字符数组中去。