首页 > 试题广场 >

不用算术运算符实现整数的加减乘除运算

[编程题]不用算术运算符实现整数的加减乘除运算
  • 热度指数:1215 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
给定两个32位整数a和b。要求不使用算术运算符,分别实现a和b的加减乘除运算。如果给定的a和b执行加减乘除的某些结果本来就会导致数据的溢出,那么你实现的函数不需要对那些结果负责(你的输出和加减乘除溢出的结果保持一致就行)。

输入描述:
输出一行,包含两个整数a和b(a和b均为32位整数)和一个运算符,运算符为“+”,“-”,“*”,"\"中的一个。(数据保证不会出现除0的情况)


输出描述:
输出一个整数,为上述表达式计算出的结果。
示例1

输入

2 * 4

输出

8
示例2

输入

5 / 4

输出

1
示例3

输入

3 + 23

输出

26

备注:
时间复杂度,额外空间复杂度
有了加法可以复用,完成减法、乘法和除法操作。
  1. 加法:两个数的“异或”为无进位和,两个数的“与”再左移一位为进位数,当进位不为0时反复调用无进位和加上进位就能够通过位运算算出加法结果;
  2. 减法:直接用第一个数加上第二个数的相反数就行,一个数的相反数为其取反再加1。
  3. 乘法:用竖式模拟,假设有x和y两个数,从右往左逐位检查y的各位是否为1(通过y的右移来完成这个检查),为1时就将x累加到结果上,由于在竖式乘法中横线等号下方的数会向左不断偏移一位来排列,然后通过竖式加法计算得到乘法结果。因此x需要随着y的右移而左移。
  4. 除法:为乘法的逆向操作,用x自底向上减去乘法竖式横线等号下方的数,但需要考虑符号的问题。
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String expression = br.readLine();
        String[] params = expression.split(" ");
        int x = Integer.parseInt(params[0]), y = Integer.parseInt(params[2]);
        String operator = params[1];
        if(operator.indexOf("+") > -1){
            System.out.println(add(x, y));
        }else if(operator.indexOf("-") > -1){
            System.out.println(subtract(x, y));
        }else if(operator.indexOf("*") > -1){
            System.out.println(multiply(x, y));
        }else{
            System.out.println(divide(x, y));
        }
    }
    
    private static int add(int sum, int carry) {
        if(carry == 0) return sum;     // 进位为0,直接返回num
        // 异或为无进位和,
        return add(sum ^ carry, (sum & carry) << 1);
    }
    
    private static int subtract(int x, int y) {
        return add(x, add(~y, 1));
    }
    
    private static int multiply(int x, int y) {
        int res = 0;
        while(y != 0){
            if((y & 1) != 0) res = add(res, x);     // 看y的最后一位是否为1
            x <<= 1;
            y >>>= 1;      // y右移
        }
        return res;
    }
    
    private static int divide(int a, int b) {
        // 先把两个数转成正数
        int x = a < 0? add(~a, 1): a;
        int y = b < 0? add(~b, 1): b;
        int res = 0;
        for(int i = 31; i >= 0; i--){
            if((x >> i) >= y) {
                res |= (1 << i);               // 将res从右往左的第i位标记为1
                x = subtract(x, y << i);       // x减去y向左移i位的结果
            }
        }
        // 同号直接返回结果,异号返回相反数
        return ((a <= 0 && b <= 0) || (a >= 0 && b >= 0))? res: add(~res, 1);
    }
}

编辑于 2021-11-19 11:19:53 回复(0)
import java.util.*;

public class Main {
	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		int n = scanner.nextInt();
        String operator = scanner.next();
        int m = scanner.nextInt();
        int res = 0;
        switch(operator){
            case "+":
                res = add(n,m);
                break;
            case "-":
                res = minus(n,m);
                break;
            case "*":
                res = multi(n,m);
                break;
            case "/":
                res = div(n,m);
                break;
        }
        System.out.print(res);
            
	}
    
    public static int add(int a,int b){
        int carry = (a&b) << 1;
        int noCarrySum = a ^ b;
        int sum = noCarrySum;
        while(carry != 0){
            sum = noCarrySum ^ carry;
            carry = (noCarrySum & carry) << 1;
            noCarrySum = sum;
        }
        return sum;
    }
    
    public static int minus(int a,int b){
        return add(a,add(~b,1));        
    }
    
    public static int multi(int a,int b){
        int res = 0;
        while(b!=0){
            if((b & 1) != 0){
                res = add(res,a);
            }
            b >>= 1;
            a <<= 1;
        }
        return res;
    }
    
    public static int div(int a,int b){
       
        return (a/b);
    }
}

发表于 2019-10-22 12:04:49 回复(1)