我正在尝试在Java中实现C/C++ atoi函数,下面是代码片段
for (int j = 0; j < s.length(); j++) {
int digit = Character.digit(s.charAt(j), 10);
if (sum < limit/10) {
if (neg) return Integer.MIN_VALUE;
return Integer.MAX_VALUE;
}
sum *= 10;
if (sum < limit + digit) {
if (neg) return Integer.MIN_VALUE;
return Integer.MAX_VALUE;
}
sum -= digit;
}
对于第 "if (sum < limit + digit) {"
行,这是正确的,但是,如果我使用 "sum - digit < limit"
,它会得到错误的结果,例如输入"-2147483649",错误的结果2147483647,应该是 -2147483648。
我想通了,因为总和 - 数字可能溢出,所以这涉及到另一个问题:
int sum = Integer.MAX_VALUE;
System.out.println(sum < Integer.MAX_VALUE + 1);
为什么这打印是假的?背后的逻辑是什么?
> Integer.MAX_VALUE + 1
等于 Integer.MIN_VALUE
,如果你用十六进制查看它们会更明显:
Integer.MAX_VALUE = 0x7fffffff
1 = 0x00000001
---------- +
0x80000000
0x80000000
也被称为Integer.MIN_VALUE
。
显然,没有比Integer.MIN_VALUE
更低的int
了。
此外,试图通过查看一个数字是否大于最大可能的值来测试它是否溢出从根本上是错误的。它不能大于最大可能的值,这就是"最大可能"的含义。此外,你不能拿一个数字,查看它,并确定它是否溢出,因为每个数字都可能是非溢出计算的结果(实际上只是将其写为常量)和溢出计算的结果。你需要知道你是如何得到这个号码的。
如果将Integer.MAX_VALUE
和1
相加,那么该总和将溢出,因此sum
不会小于结果的"总和",Integer.MIN_VALUE
,所以它是false
。
要使其正常工作,您可以将Integer.MAX_VALUE
转换为long
,这样就不会发生溢出,并且比较将正常工作。
System.out.println(sum < (long) Integer.MAX_VALUE + 1);
输出:
true
仅供参考:Integer.parseInt(String)
做你正在写的。
为什么这打印是假的?背后的逻辑是什么?
System.out.println(sum < Integer.MAX_VALUE + 1);
这会打印错误,因为Integer.MAX_VALUE + 1 == Integer.MIN_VALUE
.所以这相当于
System.out.println(sum < Integer.MIN_VALUE);
没有比最小值更小的了。