aritmética e Álgebra - prof. jacson...
TRANSCRIPT
Introdução
2016-I2
Forte relação entre Matemática e Computação
Aritmética e Álgebra são as partes maiselementares da matemática
Alguns problemas usam estes conceitos deforma não-elementar.
Máquina Aritmética
2016-I3
Máquina Aritmética
2016-I4
Números float possuem magnitude muitogrande
Com Double precision essa magnitude é aindamaior
Mesmo assim é restrita: a * 2c, onde a e c sãoum número pré-determinado de bits
Observe que apesar disso float não te permitecontar números muito grandes! Portanto useintegers e long
Máquina Aritmética
2016-I5
Números positivos (binário positivos)Números Negativos (complemento de dois)
Bibliotecas:stdlib.h (Valor absoluto e números aleatórios)math.h (Piso, teto, raiz-quadrada e exponencial)
Classe Integer tem a precisão e magnitude queprecisamos. Porém em alguns problemas vocêterá que criar seu tipo específico
Inteiros de Alta Precisão
2016-I6
Representar enormes números inteiros exigemque sejam representados como strings.
1) Arrays de Dígitos – Representar um númerointeiro como um vetor de dígitos, sendo omenos significativo o primeiro elemento dovetor. Armazenar a quantidade de dígitos
2) Listas Encadeadas de Dígitos – Usadassomente se o limite superior não for definido,por ser dinâmicas.
Exemplo: Inteiro de Alta Precisão
2016-I7
#define MAXDIGITS 100 /* maximum length bignum */
#define PLUS 1 /* positive sign bit */
#define MINUS -1 /* negative sign bit */
typedef struct {char digits[MAXDIGITS]; /* represent the number */int signbit; /* PLUS or MINUS */int lastdigit; /* index of high-order digit */
} bignum;
Impressão
2016-I8
print_bignum(bignum *n){
int i;
if (n->signbit == MINUS) printf("- ");for (i=n->lastdigit; i>=0; i--)
printf("%c",’0’+ n->digits[i]);
printf("\n");}
Adição
2016-I9
Somar dois números: Da direita para esquerda!
Respeitar o “Mais um”
Números Negativos na Adição vão sersubtraídos. Por isso sinal dos números deve serrespeitado.
Adição
2016-I10
add_bignum(bignum *a, bignum *b, bignum *c){
int carry; /* carry digit */int i; /* counter */
initialize_bignum(c);
if (a->signbit == b->signbit) c->signbit = a->signbit;else {if (a->signbit == MINUS) {
a->signbit = PLUS;subtract_bignum(b,a,c);a->signbit = MINUS;
} else {b->signbit = PLUS;subtract_bignum(a,b,c);b->signbit = MINUS;
}return;
}
c->lastdigit = max(a->lastdigit,b->lastdigit)+1;carry = 0;
for (i=0; i<=(c->lastdigit); i++) {c->digits[i] = (char)
(carry+a->digits[i]+b->digits[i]) % 10;carry = (carry + a->digits[i] + b->digits[i]) / 10;
}
zero_justify(c);}
Zero a Esquerda
2016-I11
Cuidado na hora de trabalhar com o signbit
Adição é facilitada preenchendo os dígitos dealta ordem com 0 e tratar o “mais um” finalcomo caso especial de dígito extra
A função zero_justify ajusta o último dígitopara evitar “zeros a esquerda
2016-I12
zero_justify(bignum *n){
while ((n->lastdigit > 0)&& (n->digits[n->lastdigit]==0))
n->lastdigit--;
if ((n->lastdigit == 0) && (n->digits[0] == 0))n->signbit = PLUS; /* hack to avoid -0 */
}
Zero a Esquerda
Subtração
2016-I13
A subtração é mais complicada
Necessita de “empréstimos” e garantia osempréstimos terminam
Por isso, é melhor ter certeza de que o númerode maior magnitude não ultrapassa o limite.
Subtração
2016-I14
subtract_bignum(bignum *a, bignum *b, bignum *c){
int borrow; /* anything borrowed? */int v; /* placeholder digit */int i; /* counter */
if ((a->signbit == MINUS) || (b->signbit == MINUS)) {b->signbit = -1 * b->signbit;add_bignum(a,b,c);b->signbit = -1 * b->signbit;return;
}
if (compare_bignum(a,b) == PLUS) {subtract_bignum(b,a,c);c->signbit = MINUS;return;
}
Subtração
2016-I15
c->lastdigit = max(a->lastdigit,b->lastdigit);borrow = 0;
for (i=0; i<=(c->lastdigit); i++) {v = (a->digits[i] - borrow - b->digits[i]);if (a->digits[i] > 0)
borrow = 0;if (v < 0) {
v = v + 10;borrow = 1;
}
c->digits[i] = (char) v % 10;}
zero_justify(c);}
Comparação
2016-I16
É necessário decidir qual dos dois números émaior.
Isso requer um operador de comparação.
A comparação procede do dígito da esquerda(dígito mais significativo) para a direita.
Antes compara o bit de sinal.
2016-I17
compare_bignum(bignum *a, bignum *b){
int i; /* counter */
if ((a->signbit==MINUS) && (b->signbit==PLUS)) return(PLUS);if ((a->signbit==PLUS) && (b->signbit==MINUS)) return(MINUS);if (b->lastdigit > a->lastdigit) return (PLUS * a->signbit);if (a->lastdigit > b->lastdigit) return (MINUS * a->signbit);
for (i = a->lastdigit; i>=0; i--) {if (a->digits[i] > b->digits[i])
return(MINUS * a->signbit);if (b->digits[i] > a->digits[i])
return(PLUS * a->signbit);}return(0);
}
Comparação
2016-I18
multiply_bignum(bignum *a, bignum *b, bignum *c){
bignum row; /* represent shifted row */bignum tmp; /* placeholder bignum */int i,j; /* counters */
initialize_bignum(c);
row = *a;
for (i=0; i<=b->lastdigit; i++) {for (j=1; j<=b->digits[i]; j++) {
add_bignum(c,&row,&tmp);*c = tmp;
}digit_shift(&row,1);
}
c->signbit = a->signbit * b->signbit;zero_justify(c);
}
Multiplicação
2016-I19
digit_shift(bignum *n, int d) /* multiply n by 10ˆd */{
int i; /* counter */
if ((n->lastdigit == 0) && (n->digits[0] == 0)) return;
for (i=n->lastdigit; i>=0; i--)n->digits[i+d] = n->digits[i];
for (i=0; i<d; i++) n->digits[i] = 0;
n->lastdigit = n->lastdigit + d;}
Recuo do Dígito
2016-I20
divide_bignum(bignum *a, bignum *b, bignum *c){
bignum row; /* represent shifted row */bignum tmp; /* placeholder bignum */int asign, bsign; /* temporary signs */int i,j; /* counters */
initialize_bignum(c);
c->signbit = a->signbit * b->signbit;
asign = a->signbit;bsign = b->signbit;
a->signbit = PLUS;b->signbit = PLUS;
initialize_bignum(&row);initialize_bignum(&tmp);
c->lastdigit = a->lastdigit;
Divisão
2016-I21
for (i=a->lastdigit; i>=0; i--) {digit_shift(&row,1);row.digits[0] = a->digits[i];c->digits[i] = 0;while (compare_bignum(&row,b) != PLUS) {
c->digits[i]++;subtract_bignum(&row,b,&tmp);row = tmp;
}}
zero_justify(c);
a->signbit = asign;b->signbit = bsign;
}
Divisão
Divisão
2016-I22
Essa operação calcula apenas a divisão inteira
Ignora o resto
Para calcular o resto basta fazer:c = a – b*(a/b)
Exponenciação
2016-I23
A exponenciação é feita por multiplicaçõessucessivas
an = an/2 x an/2 x an%2
Isso requer um número logarítmico demultiplicações: O(log2 n)
Exercícios
2016-I24
• Primary Arithmetic
• A Multiplication Game
• Polynomial Coefficients
• Reverse and Add
• Ones