Programação imperativa 3. Mais funções 3. Mais funções Funções. Escolha binária. Números inteiros. 2 3. Mais funções Funções. Escolha binária. Números inteiros. 3 As funções de cálculo As funções de cálculo calculam um resultado a partir dos argumentos, tal como na matemática. O tipo do resultado. O nome da função. A lista de argumentos, cada argumento com o seu tipo. double weighted_average(double lab, double exam) { return lab * 0.4 + exam * 0.6; } A instrução return. A expressão que descreve os cálculos. 4 Distância entre dois pontos Eis uma função que calcula a distância entre dois pontos (x1, y1) e (x2, y2): double distance (double x1, double y1, double x2, double y2) { return sqrt(pow(x1-x2, 2) + pow(y1-y2, 2)); } sqrt(x), a raiz quadrada de x. pow(x, y), x elevado a y. 5 As funções de teste Tipicamente, as funções de teste não têm argumentos nem resultado, declaram variáveis para os dados e para os resultados do problemas, leem os dados, calculam os resultados e escrevem os resultados, repetidamente, até não haver mais dados: void test_distance(void) { double x1, y1; double x2, y2; double d; while (scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2) != EOF) { d = distance(x1, y1, x2, y2); printf("%f\n", d); } } 6 As funções matemáticas Função Significado sin(x) Seno de x. cos(x) Cosseno de x. tan(x) Tangente de x. atan2(y, x) Arcotangente de y/x, no intervalo [-π, π]. exp(x) Exponencial de x. log(x) Logaritmo natural de x. pow(x, y) x elevado a y. sqrt(x) Raiz quadrada de x. floor(x) Maior número inteiro menor ou igual a x. ceil(x) Menor número inteiro maior ou igual a x. fabs(x) Valor absoluto de x. Para usar, fazer #include <math.h> 7 3. Mais funções Funções. Escolha binária. Números inteiros. 8 Escolha binária Por vezes, a expressão dos cálculos envolve a escolha entre duas possibilidades: “a nota final é a média ponderada (…) se a nota do exame for maior ou igual a 8.5; caso contrário, é a nota do exame (…)”. double grade_exact(double lab, double exam) { return exam < 8.5 ? exam : weighted_average(lab, exam); } 9 Expressão condicional x ? y : z O valor de x ? y : z é y, se x for verdadeiro, e é z, se x for falso. Se x for verdadeiro, z não é avaliado; se x é falso, y não é avaliado. double grade_exact(double lab, double exam) { return exam < 8.5 ? exam : weighted_average(lab, exam); } 10 Arredondamento x 0.5 , se x 0.0 r ( x) x 0.5 , se x 0.0 double round(double x) { return x < 0.0 ? ceil(x-0.5) : floor(x+0.5); } void test_round(void) { double x; double z; while (scanf("%lf", &x) != EOF) { z = round(x); printf("%f\n", z); } } 11 Instrução if-else Podemos usar a instrução if-else em vez da expressão condicional: double grade_exact(double lab, double exam) { if (exam < 8.5) return exam; else return weighted_average(lab, exam); } double round(double x) { if (x < 0.0) return ceil(x-0.5); else return floor(x+0.5); } 12 Instrução if-else, significado if (B) S else R true S B false R 13 Decomposição funcional double grade_final(double lab, double exam) { return round(grade_exact(lab, exam)); } A função grade_final chama as funções round e grade_exact. A função round chama as funções floor e ceil. A função grade_exact chama a função weighted_average. 14 Formatação dos números double A nota final deve ser escrita sem parte decimal: void test_grade_final(void) { double lb; double ex; double ge; double gf; while (scanf("%lf%lf", &lb, &ex) != EOF) { ge = grade_exact(lb, ex); gf = grade_final(lb, ex); printf("%.1f %.1f %f %.0f\n", lb, ex, ge, gf); } } Usar uma casa decimal. Usar seis casas decimais, por defeito. Não usar nenhuma casa decimal, nem sequer o ponto. 15 3. Mais funções Funções. Escolha binária. Números inteiros. 16 Números inteiros O tipo double representa os números reais; o tipo int representa os números inteiros. O intervalos dos números inteiros representáveis é [-231..231-1], isto é, [-2147483648.. 2147483647]. 2147483647 é um pouco mais do que dois mil milhões. Para os reais o intervalo vai de 1.7*10-308 a 1.7*10308 (tanto positivos como negativos), com precisão até 15 algarismos decimais. Convém distinguir bem int e double. 17 Problema da potência minorante A potência minorante de um número inteiro positivo, para uma certa base, é a maior potência dessa base que é menor ou igual ao número. Para a base 10, calcula-se de cabeça: pm(3781) = 1000; pm(91) = 10; pm(100) = 100; pm(8) = 1. Como programar? 18 Como não programar Não vale fazer uma análise por casos exaustiva: int powerless10_very_bad(int x) { if (x < 10) return 1; else if (x < 100) return 10; else if (x < 1000) return 100; else if (x < 10000) return 1000; else ...; } 19 Aproveitando a ideia… Na verdade só há dois casos. Se x é menor do que 10, o resultado é 1; se não, o resultado é 10 vezes mais do que o resultado que se obteria para um número 10 vezes menor do que x: int powerless10(int x) { if (x < 10) return 1; else return 10 * powerless10(x / 10); } 20 Base 2 Em programação interessa-nos a base 2: int powerless(int x) { if (x < 2) return 1; else return 2 * powerless(x / 2); } Variante, com expressão condicional: int powerless(int x) { return x < 2 ? 1 : 2 * powerless(x / 2); } 21 Calculando à mão powerless10(3785) = 10 * powerless10(378) = 10 * (10 * powerless(37)) = 10 * (10 * (10 * powerless(3))) = 10 * (10 * (10 * 1))) =… powerless (161) = 1000 = 2 * powerless(80) = 2 * (2* powerless(40)) = 2 * (2 * (2 * powerless(20))) = 2 * (2 * (2 * (2 * powerless(10)))) = 2 * (2 * (2 * (2 * (2 *powerless(5))))) = 2 * (2 * (2 * (2 * (2 * (2 * powerless(2)))))) = 2 * (2 * (2 * (2 * (2 * (2 * (2 * powerless(1))))))) = 2 * (2 * (2 * (2 * (2 * (2 * (2 * 1)))))) =… = 128 22 Função de teste void test_powerless(void) { int x; int z; while (scanf("%d", &x) != EOF) { z = powerless10(x); printf("%d\n", z); z = powerless(x); printf("%d\n", z); } } 23 Concatenação de números Queremos, dados dois números, calcular o número que se obtém concatenando as representações decimais desses números. Por exemplo concat(356, 1278) vale 3561278; concat(95, 6) vale 956; concat(81, 0) vale 810; concat(0, 672) vale 672. Como programar? 24 Como programar a concatenação Se o segundo número for menor do que 10, é fácil: multiplica-se o primeiro por 10 e soma-se o segundo. E se não? Se não, podemos começar por concatenar o primeiro número e número que se obtém do segundo eliminando o último algarismo; e depois acrescentamos o último algarismo do segundo número ao resultado. Nota: o último algarismo é o resto da divisão por 10. Nota: eliminar o último algarismo é dividir por 10. Nota: Estamos a trabalhar com números inteiros: a divisão é a divisão inteira. 25 Função de concatenação Observe: int concat(int x, int y) { if (y < 10) return x * 10 + y; else return concat(x, y / 10) * 10 + y % 10; } Quociente da divisão inteira de y por 10. Resto da divisão inteira de y por 10. 26 Função de teste void test_concat(void) { int x; int y; int z; while (scanf("%d%d", &x, &y) != EOF) { z = concat(x, y); printf("%d\n", z); } } 27 Os operadores aritméticos Operador + − * / % Significado Soma. Diferença. Produto. Quociente da divisão inteira, se ambos os operandos forem de tipo int; quociente da divisão exata, se algum deles (ou os dois) forem de tipo double. Resto da divisão inteira. Ambos os operandos têm de ser de tipo int. 28 Os operadores de comparação Operador == != < <= > >= Significado Igualdade. Não igualdade. Menor. Menor ou igual. Maior. Maior ou igual. 29