注意,我所使用的JDK版本是1.8,但我发现1.9版本的这个stringSize()方法和1.8版本的stringSize()方法的源码不一样。
1.8版本的stringSize()方法源码及中文注释如下:
final static int[] sizeTable = {9, 99, 999, 9999, 99999, 999999, 9999999,
99999999, 999999999, Integer.MAX_VALUE};
/**
* 统计传入整数的数字位数,比如123是3位数字,4568是4位数字
*
* @param x 正整数,但事实在该方法内并没有判断该数是否是一个正整数
* @return 返回x的位数
*/
static int stringSize(int x) {
// i是临时变量,用来统计一个数的位数
for (int i = 0; ; i++)
// 判断传入的参数x是否小于等于sizeTable[i],则返回x的位数
if (x <= sizeTable[i])
return i + 1;// 因为索引是从0开始的,所以要加1
}
该方法的功能是统计传入整数的数字位数,比如123是3位数字,4568是4位数字。
但需要注意的是,该方法没有用public修饰,所以无法调用,如果要尝试该功能的话,看如下代码:
public class Test {
final static int[] sizeTable = {9, 99, 999, 9999, 99999, 999999, 9999999,
99999999, 999999999, Integer.MAX_VALUE};
/**
* 统计传入整数的数字位数,比如123是3位数字,4568是4位数字
*
* @param x 正整数,但事实在该方法内并没有判断该数是否是一个正整数
* @return 返回x的位数
*/
static int stringSize(int x) {
// i是临时变量,用来统计一个数的位数
for (int i = 0; ; i++)
// 判断传入的参数x是否小于等于sizeTable[i],则返回x的位数
if (x <= sizeTable[i])
return i + 1;// 因为索引是从0开始的,所以要加1
}
public static void main(String[] args) {
// 输出数字123的位数
System.out.println(stringSize(123));// 3
// 输出数字123456的位数
System.out.println(stringSize(123456));// 6
// 但注意,传入的参数如果是负数,那么无论是几位都会返回1
System.out.println(stringSize(-123));// 1
System.out.println(stringSize(-654321));// 1
}
}
我们从上面代码中知道如果传入的参数是负数的话则无效,那么在源码中是如何使用的呢?
在源码中有两处用到:
第一处:如果是正数则直接传入,如果是负数则转换成正数传入。
第二处:如果是正数则直接传入,如果是负数则转换成正数传入。
所以该方法一定会生效,因为传入的参数一定是正数,不需要进行校验。
1.9版本的stringSize()方法的源码发生了变化,如下:
// Left here for compatibility reasons, see JDK-8143900.
static final int [] sizeTable = { 9, 99, 999, 9999, 99999, 999999, 9999999,
99999999, 999999999, Integer.MAX_VALUE };
/**
* Returns the string representation size for a given int value.
*
* @param x int value
* @return string size
*
* @implNote There are other ways to compute this: e.g. binary search,
* but values are biased heavily towards zero, and therefore linear search
* wins. The iteration results are also routinely inlined in the generated
* code after loop unrolling.
*/
static int stringSize(int x) {
int d = 1;
if (x >= 0) {
d = 0;
x = -x;
}
int p = -10;
for (int i = 1; i < 10; i++) {
if (x > p)
return i + d;
p = 10 * p;
}
return 10 + d;
}
中文注释下:
public class Test {
// 出于兼容性原因,请留在此处,请参阅JDK-8143900。
// 下面这个数组其实没有被用到过,但JDK1.9却留下了,因为JDK1.8及之前的版本会用到这个数组
static final int[] sizeTable = {9, 99, 999, 9999, 99999, 999999, 9999999,
99999999, 999999999, Integer.MAX_VALUE};
/**
* 返回给定int值的字符串表示大小,即一个数字的位数,如数字123的位数是3位,数字4567的位数是4位
*
* @param x 给定的整数
* @return 返回字符串大小,即位数
*/
static int stringSize(int x) {
// 局部变量,计数器
int d = 1;// 如果是负数则d=1,如果是正数则d=0,为什么呢?因为负数会把符号位计算在内,如-123执行的结果是4
// 判断给定的整数x是否是一个正数
if (x >= 0) {
// 并且将d重置为0
d = 0;
// 如果x是一个正数,则转换成一个负数
x = -x;
}
// 局部变量,用于循环
int p = -10;
for (int i = 1; i < 10; i++) {// 为什么是i<10,因为int数据类型的范围最大为2147483647,即10位数字
if (x > p)// 用于确定数字的位数
return i + d;
p = 10 * p;// 循环
}
return 10 + d;
}
public static void main(String[] args) {
// 输出数字123的位数
System.out.println(stringSize(2147483647));// 10
// 输出数字123456的位数
System.out.println(stringSize(123456));// 6
// 但注意,传入的参数如果是负数,那么也会返回负数的位数,但是会包括符号位在内,例如-123返回4
System.out.println(stringSize(-123));// 4
System.out.println(stringSize(-654321));// 7
}
}
看了上面的代码,我们可以引申出一个问题:如何求一个整数的位数?