开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第10天,点击查看活动详情
最近看到一个这样的题
给定两个整数,被除数 dividend 和除数 divisor。将两数相除,要求不使用乘法、除法和 mod 运算符。
当时我就蒙了,不用运算符号怎么能得到答案呢?
于是不信邪的我,直接添加代码return dividend/divisor 结果不能通过!!!!
唔,还是老老实实想想其他办法吧。
我们知道,做除法,有这么几种情况:
- 被除数为0 返回0
- 除数为1 返回被除数
- 除数被除数异号 结果为负
- 能不能除尽
在题目描述里面,给了提示:整数除法的结果应当截去(truncate)其小数部分,例如:truncate(8.345) = 8 以及 truncate(-2.7335) = -2
也就是不能除尽就截去小数部分。(截去,不是四舍五入哈)
那么先把简单的01情况写了吧。
public int divide(int dividend, int divisor){
if(dividend==0||divisor==1){return dividend;}
}
接下来这么判断符号
boolean k = (dividend > 0 && divisor > 0) || (dividend < 0 && divisor < 0);
并且把除数被除数都通过Math.abs()取绝对值。当被除数小于除数时候,标识有小数,进行移位
好像还是一点抽象。 那么我们从简单加法开始
加减乘除
我们可以发现,在二进制位运算里面,异或和求和类似
1^1=0,1^0=1,0^1=1,0^0=0
1+1=0,1+0=1,0+1=1,0+0=0
逻辑运算和求和进位一致
与逻辑运算:1&1=1,1&0=0,0&1=0,0&0=0
求进位运算:1+1=1,1+0=0,0+1=0,0+0=0
那么我们可以根据异或和逻辑和进行加法运算
eg: 3+8 temp=0011^1000=1011; b=(0011&1000)<<1=0000 a=1011=11;
int add(int a,int b){
int temp;
while(b!=0){//b=0就表示没有进位
temp=a^b;
b=(a&b)<<1;
a=temp;
}
return a;
}
减法其实也是加法,不过把减数变成他的补码形式
int sub(int a,int b)
{
b=~b+1;//将b转换为其补码形式
return add(a,b);
}
乘法运算,a*b=b个a相加;
除法运算:当被除数为0,结果全是0,并且除数不能为0,除法运算很容易想到可以转换成减法运算,即不停的用除数去减被除数,直到被除数小于除数时,此时所减的次数就是我们需要的商,而此时的被除数就是余数。这里需要注意的是符号的确定,商的符号和乘法运算中乘积的符号确定一样,即取决于除数和被除数,同号为正,异号为负;余数的符号和被除数一样
假设在计算除法时候存在小数也需要进行计算,如果是循环小数,用括号把循环部分括起来,输出字符串
首先如何记录循环?我们可以声明一个map用来标记循环,如果当前mo在map里面,标识出现过,加上括号
如何获取模:被除数%除数
整数部分:两数相除得到 小数部分:余数 * 10 / 除数
可以使用符号情况:
用哈希map判断,若有相同的余数则进入循环
先是极端情况,除数=1;输出被除数,被除数等于0,输出0(被除数)
if(被除数==0||除数==1) return String.valueOf(被除数);
因为可能存在除不尽情况,所以最好用long型;
long chushu=Math.abs((Long)除数)
long beichushu=Math.abs((Long)被除数);
声明返回值类型和存储循环的:
StringBuffer sb=new StringBuffer();
HashMap<Long,Integer> map=new HashMap<>();
先把整数部分加到sb里面
sb.append(beichushu/chushu);
long mo=n%d;
if(mo!=0) sb.append(".");
然后把当前模加入map
map.put(mo,sb.length())
当模不是0,进行循环求模 小数部分:余数 * 10 / 除数先在输出加入余数,然后修改模 mo = mo * 10 % 除数;
接下来判断是不是在map里面u,如果有,加入括号退出循环,如果没有,继续把当前模加入map。
public String fractionToDecimal(int numerator, int denominator) {
if (numerator == 0 || denominator == 1)return String.valueOf(numerator) ;
long n = Math.abs((long)numerator);
long d = Math.abs((long) denominator);
StringBuilder sb = new StringBuilder();
HashMap<Long,Integer> map = new HashMap<>();
sb.append(n / d);
long mo = n % d;
if (mo != 0)sb.append(".");
map.put(mo,sb.length());
while (mo != 0){
sb.append(mo * 10 / d);
mo = mo * 10 % d;
if (map.containsKey(mo)){
sb.insert(map.get(mo),"(");
sb.append(")");
break;
}
map.put(mo,sb.length());
}
return ( (numerator < 0 ^ denominator < 0) ? "-" : "") + sb.toString();
}