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
- A classe utiliza uma matriz de valores curtos para operar com números inteiros de tamanho de dígitos.
- 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.
- Vamos adicionar 3 sobrecargas a cada operador indicado com base na sobrecarga do operador de adição fornecida.
- Agora, a sobrecarga do operador de divisão.
- Vamos começar com o operador "igual a".
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
Passo 3
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
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.
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