EP1: problemas nas respostas 57 e 61?

EP1: problemas nas respostas 57 e 61?

por Luciano Ramalho -
Número de respostas: 2
Caros prof. Reverbel e Natan,

Constatei dois possíveis problemas no gabarito.

__________________
Problema 1: Excesso de dígitos na resposta 57

O enunciado diz "#define MAX_DIGITOS 50" mas a resposta do exemplo 57 tem 53 dígitos, conforme já indicado pelo colega André (Antonio Andre Monteiro Manoel):

57) 987654321987654321987654321987654321987654321 * 90760300 =
89639802559896102559896102559896102559896102470256300

__________________
Problema 2: Possível erro na resposta 61

Verifiquei os resultados da saida.txt com um pequeno programa em Python, pois esta linguagem possui suporte nativo a inteiros grandes. Percebi que o resultado do último exemplo não é o que acontece em Python.

Daí implementei um pequeno programa em Java, usando java.math.BigInteger, e o resultado é o mesmo do programa em Python.

Veja as saídas dos dois programas. Em cada saída, a linha que começa com 61) é o gabarito do prof. Reverbel e a linha seguinte é a calculada pelo programa:

#################
luciano@stella:~/Documents/usp/repo/mac122/ep1$ ./inteiro_grande.py
61) -123456708912345678901234567890 % 12304567089123405 = -6157816627064550
-123456708912345678901234567890 % 12304567089123405 = 6146750462058855
False
luciano@stella:~/Documents/usp/repo/mac122/ep1$ java InteiroGrande
61) -123456708912345678901234567890 % 12304567089123405 = -6157816627064550
-123456708912345678901234567890 % 12304567089123405 = 6146750462058855
false
#################

No anexo, o fonte dos dois programas em Python e Java.

Prof. Reverbel ou Natan: vocês podem confirmar?

Grato,

Luciano

PS. Suspeito que o problema tenha a ver com o tratamento do sinal. Na prática, o operador % só é útil com operandos inteiros e positivos. Eu nunca vi um uso prático real de % com um operando negativo, porque este operador é comumente usado para verificar o resto de alguma contagem dividido por alguma outra contagem, enfim, sempre lidando com números naturais.

Em resposta à Luciano Ramalho

Re: EP1: problemas nas respostas 57 e 61?

por Francisco Reverbel -
Olá Luciano,

Confirmo o problema na resposta 57. Já a resposta 61 está correta.

Você está certo quanto ao fato da dúvida na resposta 61 ser relacionada com o sinal. Quando o dividendo e o divisor têm sinais opostos, há duas maneiras de se definir o resto. Uma possibilidade é convencionar que o resto tem o sinal do dividendo. Outra possibilidade é convencionar que o resto tem o sinal do divisor. Algumas linguagens usam a primeira convenção, outras usam a segunda. A particular convenção adotada não é uma coisa muito importante... Como você observou, são escassos os usos reais do operador % com um operando negativo. Mas de qualquer modo precisamos escolher uma das convenções.

Neste EP resolvemos seguir a convenção que é usada na linguagem C (e também em Java), segundo a qual o resto tem o sinal do dividendo. Desse modo, se você usar a calculadora construída no EP para obter o resto da divisão de dois "inteiros grandes" que não sejam realmente grandes, isto é, dois números que cabem em variáveis tipo int da linguagem C (ou de Java), o resultado será igual ao do operador % da linguagem.

Os BigIntegers de Java também seguem a convenção "resto com o sinal do dividendo". O problema do teste que você anexou (refiro-me ao seu arquivo InteiroGrande.java) é que você usou o método mod, que não devolve o resto. Esse método não é equivalente ao operador % de Java! Para obter o resto (remainder), use o método divideAndRemainder da classe java.math.BigInteger. Refaça seu teste com esse método e você obterá a resposta que está no ítem 61 do arquivo saida.txt.

Reverbel
Em resposta à Francisco Reverbel

Re: EP1: problemas nas respostas 57 e 61?

por Francisco Reverbel -
Complementando... Este é um trecho da documentação da classe java.math.BigInteger:

"Semantics of arithmetic operations exactly mimic those of Java's integer arithmetic operators, as defined in The Java Language Specification. For example, division by zero throws an ArithmeticException, and division of a negative by a positive yields a negative (or zero) remainder."

Reverbel