Dúvidas

Dúvidas

by Henrique Veichun Lee -
Number of replies: 4

Olá,estou com algumas dúvidas:

1) No enunciado diz que nao é possível alterar o valor dos
   vetores num1 e num2. Isto significa que não se pode
   alterar o valor numérico que eles representam ou que não
   se pode alterar absolutamente nada? Por exemplo, num vetor
   num1 com 11 posições que representa o número +123, ele
   contera: [ +3 1 2 3 ? ? ? ? ? ? ? ]. Para fazer operações,
   poderiamos mudar o vetor para [ +3 1 2 3 0 0 0 ? ? ? ? ],
   por exemplo?
2) Na função soma_sinais_opostos á para implementar o
   algoritmo da subtração comum?
3) Quando acontece overflow devemos acertar o número de
   digitos do inteiro grande para MAX_DIGITOS ou para
   (MAX_DIGITOS + 1)?
4) A função soma1( int num[] ) pode ser implementada
    fazendo uso das funções soma_mesmo_sinal e
    soma_sinais_opostos?

Muito obrigado.

In reply to Henrique Veichun Lee

Re: Dúvidas

by Natan Costa Lima -
1) No enunciado diz que nao é possível alterar o valor dos
vetores num1 e num2. Isto significa que não se pode
alterar o valor numérico que eles representam ou que não
se pode alterar absolutamente nada? Por exemplo, num vetor
num1 com 11 posições que representa o número +123, ele
contera: [ +3 1 2 3 ? ? ? ? ? ? ? ]. Para fazer operações,
poderiamos mudar o vetor para [ +3 1 2 3 0 0 0 ? ? ? ? ],
por exemplo?



Se você fizer isto para facilitar a implementação não tem problema nenhum.
o que importa é que o número permaneça o mesmo.

Pela definição [ +3 1 2 3 ? ? ? ? ? ? ? ] é exatamente igual a [ +3 1 2 3 0 0 0 ? ? ? ? ]


2) Na função soma_sinais_opostos á para implementar o
algoritmo da subtração comum?



A função subtração pode chamar a soma_sinais_opostos.
A idéia é que as funções subtração e soma sejam parecidas tendo só chamadas para as funções soma_sinais_opostos e soma_sinais iguais


3) Quando acontece overflow devemos acertar o número de
digitos do inteiro grande para MAX_DIGITOS ou para
(MAX_DIGITOS + 1)?



No caso de overflow a função soma por exemplo devolve zero, assim quem a chamou saberá que algo deu errado e pode tomar providencias como sair do programa.
Acontece algo parecido em C quando você divide por zero. Tentem fazer um programa bobinho que tenha uma divisão por zero, o programa acaba e diz que fez uma operação ilegal. A idéia é a mesma.


4) A função soma1( int num[] ) pode ser implementada
fazendo uso das funções soma_mesmo_sinal e
soma_sinais_opostos?

sim.
In reply to Natan Costa Lima

Re: Dúvidas

by Francisco Reverbel -
Henrique: -------------------------------------------------------------------------
4) A função soma1( int num[] ) pode ser implementada
fazendo uso das funções soma_mesmo_sinal e
soma_sinais_opostos?

Natan: ------------------------------------------------------------------------------
sim.

---------------------------------------------------------------------------------------
Pode, mas isso não é uma boa idéia.

O enunciado não deixou clara a motivação para a função soma1. Quando colocamos essa função no enunciado, a nossa intenção (da Profa. Nami e minha) é que ela fosse uma função auxiliar para a operação de divisão e que ela fosse mais eficiente e simples de usar que a função soma. Na divisão por subtrações sucessivas, toda vez que você subtrai o divisor do dividendo você deve somar 1 ao "quociente parcial". A idéia é usar a função soma1 para fazer essa soma. Mas é preciso ter uma função específica para isso? A função soma não poderia ser usada? Poderia sim, mas se usarmos a função soma para somar 1 ao "quociente parcial" teremos as seguintes desvantagens:
  • A função soma trabalha com dois operandos num1 e num2. Para usar essa função precisamos de um segundo vetor de 50 dígitos (num2) e precisamos preencher esse vetor com o "inteiro grande" +1.
  • A função soma coloca o resultado num terceiro vetor res. Para usar essa função precisamos de mais um vetor de 50 dígitos (res). Além disso, como na divisão por subtrações parciais o que precisamos executar é o incremento quociente++, temos que copiar para o vetor quociente o resultado da soma, que foi colocado em res pela função soma.
É muito mais eficiente chamar uma função que adiciona 1 a um "inteiro grande" e atualiza diretamente o vetor recebido como parâmetro, de modo que esse vetor passe a representar o valor incrementado. Essa função (soma1) pode ser implementada de modo mais simples e mais eficiente que as funções soma_mesmo_sinal e soma_sinais_opostos.

Reverbel

In reply to Henrique Veichun Lee

Re: Dúvidas

by Francisco Reverbel -
Henrique: -------------------------------------------------------------------------
1) No enunciado diz que nao é possível alterar o valor dos
vetores num1 e num2. Isto significa que não se pode
alterar o valor numérico que eles representam ou que não
se pode alterar absolutamente nada? Por exemplo, num vetor
num1 com 11 posições que representa o número +123, ele
contera: [ +3 1 2 3 ? ? ? ? ? ? ? ]. Para fazer operações,
poderiamos mudar o vetor para [ +3 1 2 3 0 0 0 ? ? ? ? ],
por exemplo?

Natan: ------------------------------------------------------------------------------
Se você fizer isto para facilitar a implementação não tem problema nenhum.
o que importa é que o número permaneça o mesmo.

Pela definição [ +3 1 2 3 ? ? ? ? ? ? ? ] é exatamente igual a [ +3 1 2 3 0 0 0 ? ? ? ? ]
---------------------------------------------------------------------------------------

De fato esses dois vetores representam exatamente o mesmo número. Mesmo assim, o fato do Henrique querer colocar zeros desnecessários no vetor "para fazer operações" não me agrada... Vou explicar o que NÃO deve ser feito.

Suponha que você vai somar os números +8765 e +8995678. A operação deve ser feita apenas com os digitos significativos desses dois números. Primeiro você tem que fazer quatro somas de um dígito, fazendo a propagação do vai um, para somar 8765 com 5678. Depois você tem que propagar o último vai-um pelos dígitos restantes do número mais longo, isto é, pelo pedaço "899" do segundo número. É isso que deve ser feito. O que eu NÃO quero é que você complete os dois números com zeros à esquerda, e faça a soma com cinquenta dígitos:

+0000...000008765
+0000...008995678

Desse jeito você não precisa se preocupar com os comprimentos dos números, mas acaba fazendo um monte de somas de um dígito desnecessárias. Mesmo que os números sejam curtinhos, você trabalha sempre com 50 dígitos. Isso NÃO é uma solução aceitável!

Uma variação dessa solução ruim completaria com zeros à esquerda o número menos longo, de modo a deixar os dois números com o mesmo comprimento (mas não necessariamente com o comprimento máximo). Essa solução é menos ruim que a anterior, mas em certos casos ela ainda pode fazer muito trabalho desnecessário. Pense na soma de +11111...1111 (50 dígitos) com +1 (só 1 dígito)... Não é uma boa idéia completar o vetor do segundo número com 49 zeros antes de fazer a soma!

Uma boa solução tem a seguinte cara:

vai_um = 0;
i = 0
while (i < n_digs_num1 && i < n_digs_num2) {
/* soma o dígito num1[i] com o dígito num2[i] e com o vai_um */
/* atualiza o vai_um */
...
i++;
}
while (i < n_digs_num1) {
/* soma o dígito num1[i] com o vai_um */
/* atualiza o vai_um */
...
i++;
}
while (i < n_digs_num2) {
/* soma o dígito num2[i] e com o vai_um */
/* atualiza o vai_um */
...
i++;
}

Note que o programa entrará em no máximo um dos dois últimos laços, pois na saída do primeiro laço teremos

i == n_digs_num1
(neste caso o programa não entrará no segundo laço)

ou

i == n_digs_num2 (neste caso o programa não entrará no terceiro laço).

Reverbel
In reply to Francisco Reverbel

Re: Dúvidas

by Francisco Reverbel -
O Paca removeu a indentação do fragmento de código C que eu digitei acima.

Paciência... Acho que dá prá entender assim mesmo.

Reverbel