经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » Java相关 » Java » 查看文章
Java的字符串转int算法
来源:cnblogs  作者:noodleprince  时间:2018/9/27 16:53:55  对本文有异议

面T家,被要求实现一个字符串转整型数的算法,当时手写有点遗漏,现在回头来看看jdk的实现。
常用的是Integer.valueOf方法来实现转换:

  1. 1 public static Integer valueOf(String s) throws NumberFormatException {
  2. 2 return Integer.valueOf(parseInt(s, 10));
  3. 3 }

默认会调用parseInt方法进行转换,参数中的10说明是按照10进制进行转换的。

 

看看parseInt方法:

  1. 1 public static int parseInt(String s, int radix)
  2. 2 throws NumberFormatException
  3. 3 {
  4. 4
  5. 5 if (s == null) {
  6. 6 throw new NumberFormatException("null");
  7. 7 }
  8. 8
  9. 9 if (radix < Character.MIN_RADIX) {
  10. 10 throw new NumberFormatException("radix " + radix +
  11. 11 " less than Character.MIN_RADIX");
  12. 12 }
  13. 13
  14. 14 if (radix > Character.MAX_RADIX) {
  15. 15 throw new NumberFormatException("radix " + radix +
  16. 16 " greater than Character.MAX_RADIX");
  17. 17 }
  18. 18
  19. 19 int result = 0;
  20. 20 boolean negative = false;
  21. 21 int i = 0, len = s.length();
  22. 22 int limit = -Integer.MAX_VALUE;
  23. 23 int multmin;
  24. 24 int digit;
  25. 25
  26. 26 if (len > 0) {
  27. 27 char firstChar = s.charAt(0);
  28. 28 if (firstChar < '0') { // Possible leading "+" or "-"
  29. 29 if (firstChar == '-') {
  30. 30 negative = true;
  31. 31 limit = Integer.MIN_VALUE;
  32. 32 } else if (firstChar != '+')
  33. 33 throw NumberFormatException.forInputString(s);
  34. 34
  35. 35 if (len == 1) // Cannot have lone "+" or "-"
  36. 36 throw NumberFormatException.forInputString(s);
  37. 37 i++;
  38. 38 }
  39. 39 multmin = limit / radix;
  40. 40 while (i < len) {
  41. 41 // Accumulating negatively avoids surprises near MAX_VALUE
  42. 42 digit = Character.digit(s.charAt(i++),radix);
  43. 43 if (digit < 0) {
  44. 44 throw NumberFormatException.forInputString(s);
  45. 45 }
  46. 46 if (result < multmin) {
  47. 47 throw NumberFormatException.forInputString(s);
  48. 48 }
  49. 49 result *= radix;
  50. 50 if (result < limit + digit) {
  51. 51 throw NumberFormatException.forInputString(s);
  52. 52 }
  53. 53 result -= digit;
  54. 54 }
  55. 55 } else {
  56. 56 throw NumberFormatException.forInputString(s);
  57. 57 }
  58. 58 return negative ? result : -result;
  59. 59 }

首先看到5-17行是边界检查:

  • 如果字符串s是空指针,直接抛异常
  • 如果进制小于最小进制(常量定义为2),抛异常
  • 如果进制大于最大进制(常量定义为36),抛异常

接下来19-24行是局部变量定义,这里需要注意一个就是limit被赋值为int表示的最大正整型数的负值,也就是-2147483647

再往下看到26-38行,如果字符串s长度大于0,那么首先看看首字符

  • 如果首字符小于字符0,那么可能是符号 + 或者 - ,要区别对待了
    • 如果是符号 - ,说明是个负数,将布尔值变量negative设置为true,并将limit设置为int型整数的下限值,也就是-2147483648
    • 如果首字符不是符号 +,说明首字符既不是数字也不是符号,则抛出异常
  • 再接下来看,如果首字符是符号 - 或者 +,但是字符串长度只有1,也就是说只有一个符号,那么也是不能够转为整型数的,直接抛异常

 

再往下39-54行

局部变量mulmin赋值为limit除以当前转换的进制。接下来是一个循环,i代表处理的字符串的位数。
用局部变量digit记录字符串s第i位数字的相应进制的值,接下来又是一些判断了:

  • 如果digit小于0,抛异常
  • 如果result变量小于mulmin,抛异常,这里可以限制之后的乘法操作肯定不溢出;之后result变量乘以当前转换进制。(如果result小于mulmin也就是limit/radix了,那么后面的乘以radix肯定就会小于limit,对于负数就超过了Integer的范围,对于正数也是超过了Integer.MAX_VALUE
  • 如果此时result小于limit加上digit,抛异常,这里可以限制之后的减法操作不会溢出;之后result变量减去digit的值。(这个抛异常和上一条原因类似,也是为了防止溢出)

 

最后58行,如果negative为true,则直接返回result,否则返回负的result。

这个有点意思,如果是负数直接输出,如果是正数反而是用负数取负,负负得正来表示的
个人觉得应该是整型数从绝对值来看,负数的范围比正数大1,如果用result += digit这样来进行计算的话,那么最小值-2147483648会无法被正确转换。因为2147483640+8会得到-2147483648,然后再取负数的话,就变成0了。但是使用-=来计算,因为负数的范围更大,因此正数是可以全部表示出来的,而且不管是+0还是-0都不会有问题,都可以得到数值0

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号