Liczba najbliżej średniej

0

Witam. Przerabiam sobie kurs c++ na yt u pana Zelenta i natrafiłem na pewien problem z zadaniem.
Mam utworzyć program który wyświetli z podanych liczb tą która jest najbliżej średniej.
Tworzę go dla dowolnej ilości liczb podawanych przez użytkownika.

Problem polega na tym:

Jeśli podana przeze mnie liczba (której róznica ze srednią to "minimum") jest mniejsza od średniej to wychodzi mi głupota.
Z góry dzięki za wskazówki.

To kod:

#include <iostream>
#include <iomanip>


using namespace std;

float srednia(float *tablica,int ile);



  int main()
  {
      //Deklaracja zmiennych pomocniczych.
    
    int ile;
    float minimum;
    
    cout<<"Podaj ile liczb w tablicy: ";
    cin>>ile;

      //Deklaracja tablic.
    
    float *tab;
    tab= new float[ile];
    float *tab2;
    tab2= new float[ile];

      //Wypełnianie tablicy "tab"
    
    for(int i=0;i<ile;i++)
    {
        cout<<"Podaj liczbe: ";
        cin>>tab[i];
    }

      //Wypisanie sredniej

    cout<<setprecision(5);
    cout<<"Srednia wynosi: "<<srednia(tab,ile)<<endl;

      /*
          Obliczanie róznicy pomiędzy średnią
          a wprowadzoną zmienną a następnie zamiana
          ewentualnej ujemnej różnicy na wartość dodatnią
      */

    for(int i=0;i<ile;i++)
    {
        tab2[i]=tab[i]-srednia(tab,ile);

        if(tab2[i]<0)
        {
            tab2[i]=tab2[i]*(-1);
        }
        cout<<tab2[i]<<endl;
    }

      //Szukanie najmniejszej różnicy

    minimum=tab2[0];
    for(int i=0;i<ile;i++)
    {

        if(minimum>tab2[i])
            minimum=tab2[i];

    }

      //Wypisanie wyników

    cout<<setprecision(5);
    if(srednia(tab,ile)<0)
    cout<<"Najblizej sredniej: "<<(minimum-srednia(tab,ile))*(-1)<<endl;
    else
    cout<<"Najblizej sredniej: "<<minimum+srednia(tab,ile)<<endl;
    system("pause");

    delete [] tab;
    delete [] tab2;

    return 0;
}

  // Funkcja obliczająca średnią z podanych wartości

float srednia(float *tablica,int ile)
{
    float suma=0;
    for(int i=0;i<ile;i++)
    {
        suma+=*tablica;
        tablica++;
    }
    return suma/ile;
}
1

Nie jestem pewny czy zrozumiałem zadanie ale nie prościej jest zapisywać jedynie liczbę, która zwróciła najmniejszą wartość z działania abs(liczba - srednia) zamiast zapisywac wszystkie wartości do drugiej tablicy? Czyli na początku zakładamy, że najbliższa liczba to element 0 z tablicy więc najblizsza = tab[0]. Następnie iterując po wszystkich liczbach w tablicy sprawdzamy czy tab[i] - srednia < nablizsza - srednia. Jeżeli tak zapisz tab[i] jako najblizsza jeżeli nie iteruj dalej.

Przykład kodu:

#include <iostream>
#include <iomanip>
#include "vector"


using namespace std;

void fillTab(vector<int> &array)
{
   int number;
   cout << "Enter amount of numbers: ";
   int amount;
   cin >> amount;
   for(int i = 0; i < amount; ++i)
   {
       cin>>number;
       array.push_back(number);
   }
}

float getAverage(vector<int> array)
{
   float sum = 0;
   for(int i = 0; i < array.size(); ++i)
   {
       sum += array[i];
   }
   return sum/array.size();
}

int findTheClosest(vector<int> array, float average)
{
   if(array.empty())
       return 0;

   int closest = array[0];
   for(int i = 1; i < array.size(); ++i)
   {
       if(abs(array[i] - average) < abs(closest - average))
       {
           closest = array[i];
       }
   }
   return closest;
}
int main()
{
  vector<int> array;
   fillTab(array);
   cout << "Average: "<<getAverage(array)<<endl;
   cout<<"Average closest number: "<<findTheClosest(array, getAverage(array));
   
}

1
Galand napisał(a):

Witam. Przerabiam sobie kurs c++ na yt u pana Zelenta

Współczuje.
Krytyka tych kursów jest dość systematyczna, z powodu licznych błędów merytorycznych i nauczania złych praktyk.
Rzeczową krytykę wyszukasz na tym forum i w internecine.

Co do tematu: https://dsp.krzaq.cc/post/176/ucze-sie-cxx-kiedy-uzywac-new-i-delete/

Wersja zaawansowana: https://godbolt.org/z/Kqbrzseh1

0

a tak w skrócie - to jak to najlepiej rozwiązać od strony algorytmicznej? Czy da się za jednym przejechaniem pętli (i jakoś estymować średnią na bieżąco), czy trzeba najpierw raz przejechać, a potem drugi raz?

jeśli by mieć posortowaną tablicę, to by w sumie mogło to ułatwić znalezienie liczby, ale samo sortowanie będzie jeszcze mniej wydajne niż dwa przelecenia po tablicy.

3

Nie ma wyjścia muszą być dwa przebiegi lub przynajmniej jakaś sprytna struktura pamięci (np drzewo przedziałowe).
Średnia może zmienić się drastycznie, np: 1 2 6 1 3 9 2 3 7234823742823

0

Ciekawe, da się estymować średnią znając ilość liczb i da się też estymować tą średnią nie znając ile jest liczb na bieżąco, przy okazji jakby się budowało heap gdzie mniejsze wartości od średniej są z jednej gałęzi, a większe z drugiej można by było jakiś dziwny algorytm z tego ulepić :>

0

mamy 3 liczby 2,5,7 i chcemy policzyć średnią na bieżąco nie wiemy ile będzie liczb: pierwsza średnia 2/1, po drugiej liczbie (2/1) * (1/2) + 5/2 przy trzeciej (((2/1) * (1/2) + 5/2) * 2/3) + 7/3 === (2+5+7)/3

0

No tak, bo mamy losowe dane.
Ale jakbyśmy mieli dane prawdziwe (np. wzrost czy waga dorosłych ludzi) to one by się już tak nie różniły drastycznie (a jeśli zdarzałyby się jakieś ekstrema, to raczej wyjątki).

0
LukeJL napisał(a):

No tak, bo mamy losowe dane.
Ale jakbyśmy mieli dane prawdziwe (np. wzrost czy waga dorosłych ludzi) to one by się już tak nie różniły drastycznie (a jeśli zdarzałyby się jakieś ekstrema, to raczej wyjątki).

Jak już offtopujemy - to co rozumiesz przez drastyczną różnicę? Jak jakaś chudzina maturzystka waży 45 kg a ja ponad 90 kg to czy to jest "drastyczna różnica"?

0

Hmm, samo sortowanie może polepszyć branch predictions procesora przez to będzie szybciej przeszukiwał dane, procesor żeby wykonywać jedną instrukcję na jeden cykl musi wykonać 5 stage pipeline, w tym samym czasie ładuje inne instrukcje jeśli źle je załaduje to straci czas, instrukcje muszą być zcachowane.

0

Na marginesie szkolnego zadania - istnieje jakiś jednoprzebiegowy algorytm ?
Dowolna skończona / racjonalna ilosć zmiennych-akumulatorów ... i w wyniku "ta upragniona" wartość...

0

Czat GPT poległ na algorytmie jednoprzebiegowym. Tzn powiedział że się da i podał błędny kod:

double oblicz_srednia_i_znajdz_najblizsza_wartosc(double tablica[], int rozmiar_tablicy, double *najblizsza_wartosc) {
  double suma = 0.0;
  int licznik = 0;
  double srednia = 0.0;
  double roznica = 0.0;
  
  for (int i = 0; i < rozmiar_tablicy; i++) {
    suma += tablica[i];
    licznik++;
    double aktualna_roznica = fabs(tablica[i] - (suma / licznik));
    if (i == 0 || aktualna_roznica < roznica) {
      *najblizsza_wartosc = tablica[i];
      roznica = aktualna_roznica;
    }
  }
  
  srednia = suma / licznik;
  return srednia;
}

XD Może jeszcze dziś nas nie zwolnią XD

1 użytkowników online, w tym zalogowanych: 0, gości: 1