Escreva funções que calculam:
  • a soma dos elementos de um vetor;
  • a média dos elementos de um vetor;
  • o desvio padrão dos elementos de um vetor;
  • o número de elementos repetidos em um vetor;
  • o elemento que corresponde à mediana de um vetor e
  • a moda dos elementos de um vetor.
Estas funções devem receber como parâmetro um vetor de números reais e um número inteiro indicando o tamanho deste vetor. Tente criar funções auxiliares para facilitar a organização do código.

Passo 1

O enunciado pede funções que recebam um vetor de números reais e seu tamanho (um inteiro) e retornem os seguintes valores:
  • a soma dos elementos do vetor;
  • a média dos elementos do vetor;
  • o desvio padrão dos elementos do vetor;
  • o número de elementos repetidos no vetor;
  • o elemento que corresponde à mediana do vetor;
  • a moda dos elementos do vetor.
Informações relevantes dadas (implícitas no enunciado):
  • Cada função receberá dois parâmetros: um ponteiro para um vetor de números reais e um inteiro que indica o tamanho do vetor. Em termos matemáticos: o vetor será (x_1, x_2, \dots, x_n) e o inteiro é n.
  • Não foi especificado tratamento de casos como n \le 0 ou empates na moda; será necessário escolher uma política e documentá‑la.
  • Foi sugerido “criar funções auxiliares” para organizar o código.
O enunciado pediu explicitamente funções — não pediu uma linguagem, então vou implementar em linguagem C (ferramenta comum em provas e exercícios de programação) e criar funções auxiliares para copiar e ordenar o vetor, além de uma função comparadora para o qsort.

Passo 2

Decisão de métodos e políticas (explicando o porquê, conforme pedido):
  • Linguagem: C. É uma escolha padrão para exercícios de algoritmos; o código fica claro e próximo do que costuma ser exigido em provas.
  • Ordenação: vou usar a função padrão qsort da biblioteca C para simplificar e focar nas funções pedidas (o custo será O(n\log n)). Para não modificar o vetor original, vou sempre trabalhar numa cópia quando precisar de ordenação.
  • Média: usarei a fórmula clássica:
\bar{x} = \dfrac{1}{n}\sum_{i=1}^{n} x_i.
  • Desvio padrão: como não foi especificado se é a amostral ou populacional, escolho o desvio padrão populacional (fórmula mais direta) — isto é,
\sigma = \sqrt{\dfrac{1}{n}\sum_{i=1}^{n} (x_i - \bar{x})^2}.
Observação: se a prova pedir amostral, a fórmula é com (n-1) no denominador; aqui uso n.
  • Mediana: após ordenar os n valores (em ordem crescente), se n for ímpar a mediana é o elemento do meio; se n for par a mediana é a média dos dois elementos centrais. Em termos de índices (0‑based): elemento central é o índice (n-1)/2 quando n é ímpar; quando n é par usamos a média de a[n/2 - 1] e a[n/2] .
  • Moda: para números reais podem existir empates na frequência. Vou definir a política de desempate: retornar o menor valor (em sentido numérico) entre os que têm maior frequência. Como trabalhar com números reais pode ter problemas de igualdade por precisão, assumo que os valores no vetor são comparáveis com igualdade direta (ou seja, valores exatamente iguais). Essa é uma escolha habitual em exercícios que trabalham com arrays de reais vindos de entrada exata.
  • Número de elementos repetidos: a expressão é ambígua. Vou adotar esta definição (e explicá‑la): o número de elementos que fazem parte de grupos com frequência maior que 1, contando todas as ocorrências. Exemplo: para (1,1,1,2,3,3) o retorno será 5 (porque existem três ocorrências de 1 e duas de 3, totalizando 5 elementos que são repetidos). Se preferir a outra interpretação (número de valores distintos que se repetem — aqui seria 2 para o mesmo exemplo), dá para ajustar facilmente.
  • Tratamento de casos inválidos: se n \le 0, as funções que retornam número real (média, desvio, mediana, moda) retornarão NAN (valor especial de math.h) para indicar resultado indefinido; soma retorna 0 para conveniência; contagem de repetidos retorna 0.

Passo 3

Explicação detalhada e algoritmo para cada função (passo a passo para entender e poder reproduzir na prova):
  1. Soma
  • Fórmula: \displaystyle S=\sum_{i=1}^{n} x_i.
  • Algoritmo: somar iterativamente cada elemento num acumulador s.
  • Complexidade: O(n).
  1. Média
  • Fórmula já dada: \bar{x} = \dfrac{S}{n}, onde S é a soma.
  • Implementação prática: reaproveitar a função soma para calcular \bar{x}.
  • Atenção: verificar n>0.
  1. Desvio padrão (populacional)
  • Fórmula: \displaystyle \sigma = \sqrt{\dfrac{1}{n}\sum_{i=1}^{n} (x_i - \bar{x})^2}.
  • Implementação prática (duas passagens, estável o suficiente para provas):
    • Passo A: calcular \bar{x}.
    • Passo B: somar (x_i - \bar{x})^2 para todos i.
    • Passo C: dividir por n e tirar raiz quadrada.
  • Complexidade: O(n).
  1. Mediana
  • Procedimento:
    • Fazer uma cópia do vetor e ordenar essa cópia em ordem crescente.
    • Se n é ímpar, retornar o valor central.
    • Se n é par, retornar a média dos dois centrais.
  • Observação: copiar o vetor garante que a função não altere a entrada original.
  1. Moda
  • Procedimento eficiente após ordenação:
    • Ordenar o vetor copiado.
    • Passar pelo vetor contando frequência máxima maxfreq e o valor ligado a essa frequência mode.
    • Como o vetor está ordenado em ordem crescente, o primeiro valor que alcançar maxfreq será o menor entre empates — isso implementa nossa política de desempate.
  • Complexidade: ordenação domina, O(n\log n).
  1. Número de elementos repetidos (minha definição escolhida)
  • Após ordenar a cópia:
    • Percorrer a cópia identificando blocos de valores iguais; para cada bloco com frequência f > 1, somar f ao contador de repetidos.
    • Retornar esse contador.
  • Exemplo: vetor (1,1,2,3,3,4) → blocos: 1(2), 2(1), 3(2), 4(1) → repetidos = 2 + 2 = 4.

Passo 4

Implementação prática: funções auxiliares
  • cmp_double: comparador para qsort.
  • copy_and_sort: aloca (com malloc) uma cópia do vetor original, copia os conteúdos e chama qsort nela. Retorna ponteiro para cópia ordenada (ou NULL se erro).
  • Essas auxiliares ajudam a manter cada função pequena e legível.
Gestão de memória:
  • Funções que chamam copy_and_sort liberam a cópia com free antes de retornar.
  • Em caso de falha de alocação, algumas funções retornam NAN ou um valor de erro (-1 para contagem, embora eu prefira 0 ou NAN como documentado).
Complexidade final:
  • Soma/média/desvio: O(n).
  • Mediana/moda/contagem repetidos: O(n\log n) por causa da ordenação.

Passo 5

Exemplos pequenos para fixar (conceito — aqui só para treinar mentalmente, sem código):
  • Vetor: (2, 1, 4, 2, 3), n=5
    • Soma: 2+1+4+2+3 = 12.
    • Média: \bar{x} = 12/5 = 2,4.
    • Ordenado: (1,2,2,3,4)
    • Mediana: elemento central = 2.
    • Moda: 2 (frequência 2).
    • Repetidos: grupo 2 tem frequência 2 → repetidos = 2.
  • Vetor: (1,1,1,2,3,3), n=6
    • Repetidos = 3 (do valor 1) + 2 (do valor 3) = 5.
    • Moda = 1 (freq 3).

Passo 6

Pronto para o código: a seguir eu criei as funções conforme explicado. Elas usam double para valores reais, int para tamanho, qsort para ordenação e math.h para sqrt e NAN. Incluí também um main de exemplo que demonstra o uso de todas as funções.

Resposta

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

/* Comparador para qsort (ordem crescente) */
static int cmp_double(const void *a, const void *b) {
    double da = *(const double*)a;
    double db = *(const double*)b;
    if (da < db) return -1;
    if (da > db) return 1;
    return 0;
}

/* Cria uma cópia ordenada do vetor v (retorna ponteiro alocado ou NULL em erro).
   O chamador deve liberar com free(). */
static double *copy_and_sort(const double *v, int n) {
    if (n <= 0) return NULL;
    double *c = (double*) malloc((size_t)n * sizeof(double));
    if (!c) return NULL;
    memcpy(c, v, (size_t)n * sizeof(double));
    qsort(c, (size_t)n, sizeof(double), cmp_double);
    return c;
}

/* Soma dos elementos */
double soma(const double *v, int n) {
    if (n <= 0) return 0.0;
    double s = 0.0;
    for (int i = 0; i < n; ++i) s += v[i];
    return s;
}

/* Média aritmética: retorna NAN se n <= 0 */
double media(const double *v, int n) {
    if (n <= 0) return NAN;
    double s = soma(v, n);
    return s / (double)n;
}

/* Desvio padrão populacional: retorna NAN se n <= 0 */
double desvio_padrao(const double *v, int n) {
    if (n <= 0) return NAN;
    double mu = media(v, n);
    double ssd = 0.0; /* soma dos quadrados das diferenças */
    for (int i = 0; i < n; ++i) {
        double d = v[i] - mu;
        ssd += d * d;
    }
    double var = ssd / (double)n;
    if (var < 0 && var > -1e-15) var = 0.0; /* proteção numérica */
    return sqrt(var);
}

/* Número de elementos repetidos (minha definição: conta todas as ocorrências
   que pertencem a valores com frequência > 1).
   Ex.: (1,1,1,2,3,3) -> retorna 5.
   Retorna 0 se n <= 0. */
int numero_elementos_repetidos(const double *v, int n) {
    if (n <= 0) return 0;
    double *a = copy_and_sort(v, n);
    if (!a) return 0; /* em caso de falha de alocação, devolve 0 */
    int count = 0;
    int i = 0;
    while (i < n) {
        int j = i + 1;
        while (j < n && a[j] == a[i]) ++j;
        int freq = j - i;
        if (freq > 1) count += freq;
        i = j;
    }
    free(a);
    return count;
}

/* Mediana: retorna NAN se n <= 0.
   Se n ímpar, retorna o valor do meio; se par, retorna a média dos dois do meio. */
double mediana(const double *v, int n) {
    if (n <= 0) return NAN;
    double *a = copy_and_sort(v, n);
    if (!a) return NAN;
    double med;
    if (n % 2 == 1) {
        med = a[(n - 1) / 2];
    } else {
        med = (a[n/2 - 1] + a[n/2]) / 2.0;
    }
    free(a);
    return med;
}

/* Moda: retorna o valor (double) com maior frequência.
   Em caso de empate, retorna o menor valor (política definida).
   Retorna NAN se n <= 0. */
double moda(const double *v, int n) {
    if (n <= 0) return NAN;
    double *a = copy_and_sort(v, n);
    if (!a) return NAN;
    double best_val = a[0];
    int best_freq = 1;
    int i = 0;
    while (i < n) {
        int j = i + 1;
        while (j < n && a[j] == a[i]) ++j;
        int freq = j - i;
        if (freq > best_freq) {
            best_freq = freq;
            best_val = a[i];
        }
        /* se freq == best_freq não atualizamos: mantendo o primeiro (menor) valor */
        i = j;
    }
    free(a);
    return best_val;
}

/* Exemplo de uso */
int main(void) {
    double v[] = {2.0, 1.0, 4.0, 2.0, 3.0};
    int n = (int)(sizeof(v)/sizeof(v[0]));

    printf("Vetor: ");
    for (int i = 0; i < n; ++i) printf("%g ", v[i]);
    printf("\n");

    printf("Soma: %g\n", soma(v, n));
    printf("Media: %g\n", media(v, n));
    printf("Desvio padrao: %g\n", desvio_padrao(v, n));
    printf("Numero de elementos repetidos: %d\n", numero_elementos_repetidos(v, n));
    printf("Mediana: %g\n", mediana(v, n));
    printf("Moda: %g\n", moda(v, n));

    return 0;
}

Exercícios relacionados