No utilice operadores aritméticos para implementar operaciones de suma, resta, multiplicación y división de enteros

No utilice operadores aritméticos para implementar operaciones de suma, resta, multiplicación y división de enteros

Descripción del Título:

Dados dos enteros de 32 bits ay b. Se requiere no utilizar operadores aritméticos y realizar las operaciones de suma, resta, multiplicación y división de ayb respectivamente. Si los a y b dados realizan algunos resultados de suma, resta, multiplicación y división que habrían causado un desbordamiento de datos, entonces la función que implementa no necesita ser responsable de esos resultados (su salida es consistente con el resultado de suma, resta, multiplicación y desbordamiento de división).

Ingrese una descripción:

Ingrese una línea que contenga dos números enteros ayb (tanto a como b son números enteros de 32 bits) y un operador. El operador es uno de "+", "-", "*" y "". (La garantía de datos no se dividirá por 0)

Descripción de salida:

Genera un número entero, que es el resultado calculado por la expresión anterior.

Ejemplo 1
entrar
2 * 4
Salida
8
Ejemplo 2
entrar
5 / 4
Salida
1
Ejemplo 3
entrar
3 + 23
Salida
26
Observaciones:

Complejidad temporal O (1) O (1)O ( 1 ) , complejidad adicional del espacioO (1) O (1)O ( 1 )


responder:

El punto más importante de esta pregunta es: la suma se realiza y la substracción, multiplicación y división subsiguientes se pueden convertir en operaciones de suma.

adición:

  • No consideres el caso de carry: a + b = a ^ b;

  • Considere únicamente el caso de acarreo: a + b = (a & b) << 1;

Agregar el resultado de no considerar el acarreo y solo considerar el acarreo es el resultado final. Es decir, repita el proceso anterior hasta que el acarreo sea 0.

Sustracción:

ab = a + (- b), así que convierta b en el complemento de uno y simplemente agréguelo directamente.

multiplicación:

una ∗ segundo = una ∗ 2 0 ∗ segundo 0 + una ∗ 2 1 ∗ segundo 1 + una ∗ 2 2 ∗ segundo 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}unsegundo=un20segundo0+un21segundo1+un22segundo2+. . .+un23 1segundo3 1

Calcule directamente de acuerdo con esta ley. Nota: b puede ser un número negativo y debe tratarse.

división:

La operación inversa de multiplicación se enumera desde el orden más alto, si (a >> i)> = b, entonces a - = (b << i) y registre el resultado. Necesita tratamiento especial elemento 1 << 31:

  • Si tanto a como b no son el mínimo, calcule directamente;

  • Si tanto a como b son el mínimo, devuelve 1 directamente;

  • Si a no es el valor mínimo y b es el valor mínimo, devuelve 0;

  • Si a es el valor mínimo y b no es el valor mínimo, se requiere un tratamiento especial:

    • Suponiendo a = -10, b = 5, es decir, el valor máximo es 9 y el valor mínimo es -10;
    • Calcule (a + 1) / b y márquelo como c;
    • Calcule c * by márquelo como d;
    • Calcule ad y márquelo como e;
    • Calcule e / by regístrelo como ret;
    • Regresar ret + c.

    En otras palabras, es un poco difícil de calcular directamente, por lo que podemos aumentar un poco el valor mínimo y luego modificarlo.

Código:
#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);
}

Supongo que te gusta

Origin blog.csdn.net/MIC10086/article/details/109100002
Recomendado
Clasificación