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

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

题目描述:

给定两个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
备注:

时间复杂度 O ( 1 ) O(1) O(1),额外空间复杂度 O ( 1 ) O(1) O(1)


题解:

此题最最主要的的点是:加法实现,后面的减法、乘法和除法都可以转换为加法运算。

加法:

  • 不考虑进位的情况:a + b = a ^ b;

  • 只考虑进位的情况:a + b = (a&b) << 1;

把不考虑进位和只考虑进位的结果相加,就是最终的结果。也就是不断重复上面的过程,直到进位为0。

减法:

a-b = a+(-b),所以把 b 变成 补码,直接算加法即可。

乘法:

a ∗ b = a ∗ 2 0 ∗ b 0 + a ∗ 2 1 ∗ b 1 + a ∗ 2 2 ∗ b 2 + . . . + a ∗ 2 31 ∗ b 31 a*b = {a}*{2^0}*b_0+{a}*{2^1}*b_1+{a}*{2^2}*b_2+...+{a}*{2^{31}}*b_{31} ab=a20b0+a21b1+a22b2+...+a231b31

直接按照这个规律计算即可。注意:b可能是负数,需要处理一下。

除法:

乘法的逆运算,从最高位枚举,若 (a >> i) >= b,则 a -= (b << i),记录结果即可。需要特殊处理元素 1<<31 :

  • 若 a 和 b 都不是最小值,直接计算即可;

  • 若 a 和 b 都是最小值,直接返回 1 即可;

  • 若 a 不为最小值,而 b 为最小值,返回0;

  • 若 a 为最小值,而 b 不为最小值,需要特殊处理:

    • 假设 a=-10, b=5,即最大值为 9 ,最小值为 -10;
    • 计算 (a+1)/b,记为 c ;
    • 计算 c*b,记为 d;
    • 计算 a-d,记为 e;
    • 计算 e/b,记为 ret;
    • 返回 ret+c 。

    也就是说直接计算有点困难,那么我们把最小值增加一点,然后修正即可。

代码:
#include <cstdio>
using namespace std;
const int MIN = 1 << 31;

int add( int a, int b ) {
    
    
    int ret = a;
    while ( b ) {
    
    
        ret = a ^ b;
        b = ( a & b ) << 1;
        a = ret;
    }
    return ret;
}

int negNum( int n ) {
    
    
    return add( ~n, 1 );
}

int minus( int a, int b ) {
    
    
    return add( a, negNum( b ) );
}

inline bool isNeg( int n ) {
    
    
    return n < 0;
}

int multi( int a, int b ) {
    
    
    int ret = 0;
    int x = isNeg( a ) ? negNum( a ) : a;
    int y = isNeg( b ) ? negNum( b ) : b;
    while ( y ) {
    
    
        if ( y & 1) ret = add( ret, x );
        y >>= 1;
        x <<= 1;
    }
    return isNeg( a ) ^ isNeg( b ) ? negNum( ret ) : ret;
}

int div( int a, int b ) {
    
    
    int x = isNeg( a ) ? negNum( a ) : a;
    int y = isNeg( b ) ? negNum( b ) : b;
    int ret = 0;
    for ( int i = 31; i > -1; i = minus( i, 1 ) ) {
    
    
        if ( ( x >> i ) >= y ) {
    
    
            ret |= ( 1 << i );
            x = minus( x, y << i );
        }
    }
    return isNeg( a ) ^ isNeg( b ) ? negNum( ret ) : ret;
}

int divide( int a, int b ) {
    
    
    if ( a == MIN && b == MIN ) return 1;
    else if ( b == MIN ) return 0;
    else if ( a == MIN ) {
    
    
        int ret = div( add( a, 1 ), b );
        return add( ret, div( minus( a, multi( ret, b ) ), b ) );
    } else return div( a, b );
}

int main(void) {
    
    
    int a, b;
    char op;
    scanf("%d %c %d", &a, &op, &b);
    int ret;
    if ( op == '+' ) ret = add( a, b );
    else if ( op == '-' ) ret = minus( a, b );
    else if ( op == '*' ) ret = multi( a, b );
    else ret = divide( a, b );
    return 0 * printf("%d\n", ret);
}

猜你喜欢

转载自blog.csdn.net/MIC10086/article/details/109100002