Classe HugeInt. Uma máquina com inteiros de 32 bits

pode representar inteiros no intervalo de aproximadamente

–2 bilhões a +2 bilhões. Essa restrição de tamanho

fixo raramente é problemática, mas existem aplicações

em que gostaríamos de poder usar um intervalo de

inteiros muito maior. Foi para isso que C++ foi concebida,

ou seja, para criar novos tipos de dados poderosos.

Considere a classe HugeInt das figuras 19.23 a 19.25.

Estude a classe cuidadosamente e depois resolva as seguintes

questões:

a) Descreva exatamente como ela opera.

b) Que restrições a classe tem?

c) Sobrecarregue o operador de multiplicação *.

d) Sobrecarregue o operador de divisão /.

e) Sobrecarregue todos os operadores relacionais e de

igualdade.

[Nota: não mostramos um operador de atribuição nem

um construtor de cópia para a classe HugeInteger, pois

o operador de atribuição e o construtor de cópia fornecidos

pelo compilador são capazes de copiar o dado-membro

de array inteiro corretamente.]

Passo 1

  1. A classe utiliza uma matriz de valores curtos para operar com números inteiros de tamanho de dígitos.
  2. Uma instância dessa classe pode ser inicializada passando um long ou uma string para o construtor.

    Além disso, a classe tem uma funcionalidade para adicionar:

    Dois objetos

    Um int e um objeto

    Uma string e um objeto

    Esse recurso é possível devido aos construtores implementados.

    Passo 2

  3. A classe pode operar com um número limitado de dígitos devido à implementação do array. A complexidade de tempo das operações da classe não é boa porque, para cada operação, um loop no pior caso itera por todo o array de tamanho n. Além disso, a função de sobrecarga do operador de extração não gera o valor do número se o valor for zero.
  4. Passo 3

  5. Vamos adicionar 3 sobrecargas a cada operador indicado com base na sobrecarga do operador de adição fornecida.
  6. Vamos implementar as funções de sobrecarga do operador de multiplicação.

    Primeiramente, crie um objeto e uma cópia do operando esquerdo:

    HugeInt HugeInt::operator*(const HugeInt &op2) const {

    HugeInt copy(*this), res(0);

    ...

    }

    Em seguida, entraremos em um loop que itera por todos os valores inteiros diferentes de zero da matriz do operando direito:

    HugeInt HugeInt::operator*(const HugeInt &op2) const {

    ...

    for (int i = 0; i

    int num = op2.integer[i];

    if (num > 0)

    {

    ...

    }

    }

    ...

    }

    Multiplique o operando esquerdo pelo dígito do operando direito da seguinte forma:

    HugeInt HugeInt::operator*(const HugeInt &op2) const {

    ...

    for (int i = 0; i

    int num = op2.integer[i];

    if (num > 0)

    {

    HugeInt tmp(copy);

    int carry = 0;

    for (int j = digits - 1; j >= 0; j--)

    {

    tmp.integer[j] = tmp.integer[j] * num

    + carry;

    carry = tmp.integer[j] / 10;

    tmp.integer[j] %= 10;

    }

    ...

    }

    }

    ...

    }

    Em seguida, mova os dígitos pela quantidade correspondente (método de multiplicação manual):

    // 13 * 27

    // 91

    // + 26

    // ---------

    // 351

    HugeInt HugeInt::operator*(const HugeInt &op2) const {

    ...

    for (int i = 0; i

    int num = op2.integer[i];

    if (num > 0)

    {

    ...

    for (int j = 0; j

    {

    tmp.integer[j]

    = tmp.integer[j + digits - 1 - i];

    }

    for (int j = i + 1; j

    tmp.integer[j] = 0;

    ...

    }

    }

    ...

    }

    Adicione o objeto tmp ao resultado. Por fim, retorne o objeto de resultado.

    HugeInt HugeInt::operator*(const HugeInt &op2) const {

    ...

    for (int i = 0; i

    int num = op2.integer[i];

    if (num > 0)

    {

    ...

    res = res + tmp;

    }

    }

    return res;

    }

    Para criar sobrecargas adicionais, reutilize a função definida anteriormente convertendo os diferentes tipos em uma instância de classe da seguinte maneira:

    HugeInt HugeInt::operator*(int op2) const {

    return *this * HugeInt(op2);

    }

    HugeInt HugeInt::operator*(const string &op2) const {

    return *this * HugeInt(op2);

    }

    Passo 4

  7. Agora, a sobrecarga do operador de divisão.
  8. Primeiramente, verifique se os objetos são iguais (sobrecarregaremos este operador mais tarde):

    HugeInt HugeInt::operator/(const HugeInt &op2) const {

    if (*this == op2)

    return HugeInt(1);

    ...

    }

    Em seguida, crie uma cópia do operando correto e um objeto de resultado.

    Enquanto o objeto de cópia for menor ou igual ao operando esquerdo, aumente o valor dele pelo valor do operando direito e incremente o valor do resultado:

    HugeInt HugeInt::operator/(const HugeInt &op2) const {

    ...

    HugeInt tmp = op2, res;

    while (*this >= tmp)

    {

    res = res + 1;

    tmp = tmp + op2;

    }

    return res;

    }

    Da mesma forma que fizemos com as outras duas sobrecargas do operador de multiplicação, faremos com o operador de divisão:

    HugeInt HugeInt::operator/(int op2) const {

    return *this / HugeInt(op2);

    }

    HugeInt HugeInt::operator/(const string &op2) const {

    return *this / HugeInt(op2);

    }

    Agora o operador relacional e de igualdade sobrecarrega.

  9. Vamos começar com o operador "igual a".

Itere através da matriz, comparando os valores da seguinte forma:

Adicione as sobrecargas adicionais:

bool HugeInt::operator==(int op2) const {

return *this == HugeInt(op2);

}

bool HugeInt::operator==(const string &op2) const {

return *this == HugeInt(op2);

}

Para criar a função de sobrecarga do operador "diferente de", utilizaremos o valor negado da função de sobrecarga do operador "igual a" que definimos anteriormente:

bool HugeInt::operator!=(const HugeInt &op2) const {

return !(*this == op2);

}

bool HugeInt::operator!=(int op2) const {

return !(*this == HugeInt(op2));

}

bool HugeInt::operator!=(const string &op2) const {

return !(*this == HugeInt(op2));

}

A função de sobrecarga do operador "menor que" também precisa percorrer as matrizes, comparando os valores da seguinte forma:

bool HugeInt::operator

for (int i = 0; i

{

if (integer[i]

return true;

else if (integer[i] > op2.integer[i])

return false;

}

return false;

}

bool HugeInt::operator

return *this

}

bool HugeInt::operator

return *this

}

Utilize a função de sobrecarga do operador "menor que" para criar a função de sobrecarga do operador "maior que":

bool HugeInt::operator>(const HugeInt &op2) const {

return !(*this

}

bool HugeInt::operator>(int op2) const {

return !(*this

}

bool HugeInt::operator>(const string &op2) const {

return !(*this

}

Implemente as funções de sobrecarga de operador relacional restantes usando as definidas anteriormente da seguinte forma:

bool HugeInt::operator

return *this == op2 || *this

}

bool HugeInt::operator

return *this

}

bool HugeInt::operator

return *this

}

bool HugeInt::operator>=(const HugeInt &op2) const {

return *this == op2 || *this > op2;

}

bool HugeInt::operator>=(int op2) const {

return *this >= HugeInt(op2);

}

bool HugeInt::operator>=(const string &op2) const {

return *this >= HugeInt(op2);

}

O arquivo principal demonstra brevemente a classe:

#include

#include "HugeInt.h"

using namespace std;

int main()

{

HugeInt h1(13);

HugeInt h2 = h1 * 3;

cout

if (h2 >= h1)

cout

}

Resposta

Ver o desenvolvimento