java parsInt实现原理_parseInt的实现(包含java和c语言)

jdk中的Integer类是int对象的包装类,正常的Integer占用内存开销要比int大,比例大概是1:4

今天分享的代码是Integer类中的静态方法parseInt(String,

int)。这个方法众所周知, 甚至在我们一开始学习编程时就尝试的写过这样的代码,一个正常的思路:

遍历输入的字符数组(java的字符串就是一个字符数组),

然后parse每个char,依据参数给定的进制,判断每个char是否满足,满足则继续,

否则抛出异常或中断,直到处理完毕所有字符,返回结果。

清软国际java学习java培训 软件工程师 如何学习java学习java哪里好 郑州学习java哪里好 清软国际学习java

那么我们看看jdk给出的实现:

public static int

parseInt(String s, int radix) throws NumberFormatException

{

if (s == null) {

throw new

NumberFormatException("null");

}

if (radix

< Character.MIN_RADIX) {

throw new NumberFormatException("radix "

radix

" less

than Character.MIN_RADIX");

} 清软国际java学习java培训 软件工程师 如何学习java学习java哪里好 郑州学习java哪里好 清软国际学习java

if (radix

> Character.MAX_RADIX) {

throw new NumberFormatException("radix "

radix

" greater

than Character.MAX_RADIX");

}

int result = 0;

boolean negative =

false;

int i = 0, max =

s.length();

int limit;

int multmin;

int digit;

清软国际java学习java培训 软件工程师 如何学习java学习java哪里好 郑州学习java哪里好 清软国际学习java

if (max >

0) {

if (s.charAt(0) == '-') {

negative = true;

limit = Integer.MIN_VALUE;

i ;

} else {

limit = -Integer.MAX_VALUE;

}

multmin = limit / radix;

if (i < max) {

digit = Character.digit(s.charAt(i

),radix);

if (digit < 0) {

throw

NumberFormatException.forInputString(s);

} else {

result =

-digit;

}

}

while (i < max) {

// Accumulating negatively avoids surprises near

MAX_VALUE

digit = Character.digit(s.charAt(i

),radix);

if (digit < 0) {

throw

NumberFormatException.forInputString(s);

} 清软国际java学习java培训 软件工程师 如何学习java学习java哪里好 郑州学习java哪里好 清软国际学习java

if (result < multmin) {

throw

NumberFormatException.forInputString(s);

}

result *= radix;

if (result < limit digit) {

throw

NumberFormatException.forInputString(s);

}

result -= digit;

}

} else {

throw

NumberFormatException.forInputString(s);

} 清软国际java学习java培训 软件工程师 如何学习java学习java哪里好 郑州学习java哪里好 清软国际学习java

if (negative) {

if (i > 1) {

return result;

} else {

throw

NumberFormatException.forInputString(s);

}

} else {

return -result;

}

}

清软国际java学习java培训 软件工程师 如何学习java学习java哪里好 郑州学习java哪里好 清软国际学习java

过程就是按照思路来的,但是更全面一些,首先做一些参数检查,然后定义了局部变量用于计算:

result是对应的int结果,negative对应是否是负数的判断,i是遍历用的索引指针,max代表字符串的长度,

limit是合法数字的上限(下限),digit是当前扫描到的字符对应的数字,multmin是在做乘法计算时能走到的合法下限。

严谨是这段程序最大的特点,因为有符号int的上下限是-2147483648~2147483647,可见负数表达的范围比正数多一个,

这样就好理解为什么在开头要把limit全部表达为负数(下限),这样的操作减少了后续的判断,可以一步到位,

相当于二者选择取其大一样,大的包含了小的。同理,那么multmin也就是负数了,

而且可以认为是只和进制参数radix有关系。接着每个char的扫描计算digit利用到了Character.digit(char,int)

方法,

这个方法就是在调用CharacterDataLatin1.digit(codePoint, radix) 方法,

而这个新的方法其实只是去静态数组中取个映射而已。最后当顺利的执行完while循环后,result结果也就计算好了。

清软国际java学习java培训 软件工程师 如何学习java学习java哪里好 郑州学习java哪里好 清软国际学习java

作为程序设计人员,我最初接触的语言是C ,当初用到的库函数是atoi,那么我们看看atoi的库标准实现:

int

atoi(str)

const char *str;

{

_DIAGASSERT(str != NULL);

return((int)strtol(str, (char **)NULL, 10));

}

其中调用了strtol方法,参数传递的radix是10,也就是说我们常用的atoi是默认转化字符串到10进制的。

其中开始时还进行了一个trim的操作,而且支持16进制的0x开头,可谓完全的尽善尽美啊。

清软国际java学习java培训 软件工程师 如何学习java学习java哪里好 郑州学习java哪里好 清软国际学习java

strtol方法:

#define _FUNCNAME strtol

#define __INT long

#define __INT_MIN LONG_MIN

#define __INT_MAX LONG_MAX

__INT

_FUNCNAME(const char *nptr, char **endptr, int base)

{

const char *s;

__INT acc, cutoff;

char c;

int i, neg, any, cutlim;

_DIAGASSERT(nptr != NULL);

if (base && (base

< 2 || base > 36)) {

errno = EINVAL;

return(0);

}

s = nptr;

do {

c = *s ;

} while (isspace(c));

if (c == '-') {

neg = 1;

c = *s ;

} else {

neg = 0;

if (c == ' ')

c = *s ;

}

if ((base == 0 || base == 16)

&&

c == '0'

&& (*s == 'x' || *s == 'X'))

{

c = s[1];

s = 2;

base = 16;

}

if (base == 0)

base = c == '0' ? 8 : 10;

清软国际java学习java培训 软件工程师 如何学习java学习java哪里好 郑州学习java哪里好 清软国际学习java

cutoff = neg ? __INT_MIN : __INT_MAX;

cutlim = (int)(cutoff % base);

cutoff /= base;

if (neg) {

if (cutlim > 0) {

cutlim -= base;

cutoff = 1;

}

cutlim = -cutlim;

}

for (acc = 0, any = 0;; c = *s ) {

if (!isascii(c))

break;

if (isdigit(c))

i = c - '0';

else if (isalpha(c))

i = c - (isupper(c) ? 'A' - 10 : 'a' - 10);

else

break;

if (i >= base)

break;

if (any < 0)

continue;

if (neg) {

if (acc < cutoff || (acc == cutoff

&& i > cutlim))

{

any = -1;

acc = __INT_MIN;

errno = ERANGE;

} else {

清软国际java学习java培训 软件工程师 如何学习java学习java哪里好 郑州学习java哪里好 清软国际学习java

any = 1;

acc *= base;

acc -= i;

}

} else {

if (acc > cutoff || (acc == cutoff

&& i > cutlim))

{

any = -1;

acc = __INT_MAX;

errno = ERANGE;

} else {

any = 1;

acc *= base;

acc = i;

}

}

} 清软国际java学习java培训 软件工程师 如何学习java学习java哪里好 郑州学习java哪里好 清软国际学习java

if (endptr != 0)

*endptr = __DECONST(char *, (any ? s - 1 : nptr));

return(acc);

}

当然,类似的代码还有很多,这里只列出了两大语言的库实现,总体思路是一致的,

当我们设计api时,这种编程思路和风格以及功能的考虑是我们需要学习的。

清软国际java学习java培训 软件工程师 如何学习java学习java哪里好 郑州学习java哪里好 清软国际学习java

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值