掘金更文挑战
持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第4天,点击查看活动详情
空间限制下的整型溢出判断
字符串转换为整型是常见的题目情景,一般来说,我们会这样拼接数字:
int p = 0;
int ans = 0;
while(p < s.length()){
ans *= 10;
ans += (s.charAt(p) - '0');
}
ans 初始化为0,并在循环中先乘十再加上新的数位,是一个比较优雅的小技巧,因为遍历到最后一位就不需要乘十了。
如果题目到此位置的化,就是一道比较 字符串相关的简单题了。
如果是中等题的化,会将数据输入的范围扩大,如给出超越32位有符号数极限的数字,并规定越界输出。
通常情况下只需要用long类型粗暴的比较一下就好了,但如何在只是用int变量(即32位有符号数)的同时,优雅的判断溢出呢?
只需要在循环过程中这么做:(向上溢出输出最大值,向下溢出输出最小值)
int sign = 1; //sign 从字符串的正负号中得出
int p = 0;
int ans = 0;
int p = 0;
while(p < n){
char c = str.charAt(p);
if(c <= '9' && c >= '0'){
//累加之前判断ans是否已经过大了 不然再判断要累加的数。
if(ans > (Integer.MAX_VALUE / 10) ||
(ans == (Integer.MAX_VALUE / 10) && (c-'0') > Integer.MAX_VALUE % 10)){
//Integer.MAX_VALUE % 10 其实就是 7.
if(flag == 1) return Integer.MAX_VALUE;
else return Integer.MIN_VALUE;
}
ans *= 10;
ans += c - '0';
p++;
}
}
这个技巧十分简单,符合直觉。鉴于在做题的时候,这种题目通常会给字符串里面加入乱七八糟要判断的东西,比如字母符号空格,规定一些奇怪的东西如连字符表示连接数字等等规则。能熟记这个小技巧的话,真遇到了这样的题目就能更专心模拟题目条件了。
除法取整公式
Java的整数除法本身相当于向下取整,可以使用以下公式快速计算向上取整。
以 m/n 为例, Java m/n 本身输出为商向下取整的值,设f(x)向上取整,g(x) 为向下取整
有 f(m / n) = g((m + n - 1) / n)
注意,图中被取整的是x的值,相当于函数括号中的数。
f(m / n) = g((m + n - 1) / n) = g((m-1) / n) + 1
根据取整的意义,显然,n 可以提取出来,表现在图中相当于向下取整函数整体上移 1。
此时函数图像已经基本重合,只差边界,即 x 取整数的时候(就是图中的圈圈们)。
只需证明,(m-1) / n只会在(m/n)取整数值的时候(也就是x取整数值的时候),使得g(x)减小1,即可。
由于m、n均为整数,可设 m = k*n + b (b>0)
所以可以得出:
m == k*n的时候,m-1 = (k-1)*n + (n-1)。
m == k*n + b的时候,m-1 = k*n + b-1。由于b>0,不会影响g(m-1/n)的值。