Есть такое задание: в массиве найти минимальное число. Если минимальных чисел несколько, то присвоить им среднее арифметическое исходного массива и вывести измененный массив.
Собственно, я это все сделал, однако хочу оптимизировать код, чтобы было меньше строк.
Я не прошу писать код за меня, я хочу, чтобы меня подтолкнули в правильном направлении. На другом форуме говорят, что можно все реализовать через 2 цикла, но я уже 2 дня думаю и никак не могу сообразить, как сделать.
#include "pch.h"
#include <iostream>
#include <windows.h>
#include <ctime>
int main()
{
SetConsoleOutputCP(1251);
srand(time(0));
double array[10];
double minNumber = 0.0, average = 0.0;
int counter(0);
//Заполнение и вывод массива
printf("Исходный массив:\n");
for (int i = 0; i < 10; i++) {
array[i] = 1 + rand() % 9; //Заполнение массива случайными числами от 1 до 9
printf("%.2f ", array[i]);
average = average + array[i]; //Суммируем все элементы массива
if (i == 9) //Когда массив заполнится, находим среднее арифметическое
average = average / 10;
}
minNumber = array[0];
for (int i = 0; i < 10; i++)
{
if (minNumber > array[i]) { //Сравнение элементов массива
minNumber = array[i]; //Присвоим minNumber минимальное значение
}
}
printf("\nМинимальное значение: %.2f\n", minNumber);
for (int i = 0; i < 10; i++)
{
if (array[i] == minNumber) {
counter++;
array[i] = average;
}
}
if(counter >= 2)
{
printf("\nИзмененный массив: \n");
for (int i = 0; i < 10; i++)
printf("%.2f ", array[i]);
}
printf("\n");
system("pause");
return 0;
}
Я уже писал в комментарии к вашему вопросу, что,, обычно, чем ниже квалификация программиста, тем сильнее у него желание "оптимизировать" код, стараясь, в частности, все запихнуть в один цикл. В результате код становится трудно-читаемым, а конструкции программы сильно перегружены. Старайтесь в первую очередь писать логически ясный код
Трудно-читаемый код - это всегда источник различных багов, и к тому же такой код трудно модифицировать
У вас в задании написано:
в массиве найти минимальное число. Если минимальных чисел несколько, то присвоить им среднее арифметическое исходного массива и вывести измененный массив.
Вот и следуйте букве этого задания. То есть вы сначала должны определить минимальное значение элементов в массиве, а также сколько элементов массива содержит это минимальное значение.
И только в случае, если таких элементов больше одного, то тогда заменить значения таких элементов средним значением. То есть эта часть программы выполняется только при одном условии.
Не надо делать в данной момент программы то, что в ней не требуется делать. Иначе такой код, в котором что-то делается, что в данный момент не требуется делать, будет вызывать вопросы и недоумения.
Поэтому в первую очередь надо думать не о пресловутой "оптимизации", а о качественно написанном коде логически ясным.
Старайтесь не использовать в коде магических чисел таких, как, например, 10. Используйте именованные константы.
Вот как может выглядеть ваш код.
#include <iostream>
#include <cstdlib>
#include <ctime>
int main()
{
const size_t N = 10;
double a[N];
std::srand( ( unsigned int )std::time( nullptr ) );
int MAX_VALUE = 9;
for ( auto &item : a ) item = 1 + std::rand() % MAX_VALUE;
for ( const auto &item : a ) std::cout << item << ' ';
std::cout << '\n';
double min = a[0];
size_t count = 1;
for ( size_t i = 1; i < N; i++ )
{
if ( a[i] < min )
{
min = a[i];
count = 1;
}
else if ( not( min < a[i] ) )
{
++count;
}
}
if ( count > 1 )
{
double sum = 0.0;
for ( const auto &item : a ) sum += item;
double average = sum / N;
for ( auto &item : a )
{
if ( item == min ) item = average;
}
}
for ( const auto &item : a ) std::cout << item << ' ';
std::cout << '\n';
return 0;
}
Вывод программы на консоль может быть, к примеру, следующим:
3 9 6 3 2 6 9 2 8 9
3 9 6 3 5.7 6 9 5.7 8 9
То есть в данном конкретном случае два элемента массива содержат минимальное значение, равное 2. А потмоу значения этих двух элементов массива заменяется средним арифметическим значением.
Итак, программа сначала ищет минимальное значение и количество элементов, содержащих это минимальное значение
double min = a[0];
size_t count = 1;
for ( size_t i = 1; i < N; i++ )
{
if ( a[i] < min )
{
min = a[i];
count = 1;
}
else if ( not( min < a[i] ) )
{
++count;
}
}
И лишь затем, если число элементов, содержащих найденное минимальное значение, больше 1, то происходит замена значений этих элементов средним значением.
if ( count > 1 )
{
double sum = 0.0;
for ( const auto &item : a ) sum += item;
double average = sum / N;
for ( auto &item : a )
{
if ( item == min ) item = average;
}
}
Теперь, когда имеется логически ясный код, то его легко "оптимизировать", как вы к тому стремитесь. Можно исключить отдельный цикл, который подсчитывает сумму всех элементов массива для вычисления далее среднего арифметического. (На самом деле это будет кажущаяся оптимизация, так как теперь, даже если в массиве имеется только один элемент с минимальным значением, происходит безусловное вычисление суммы всех элементов.)
В этом случае программа будет выглядеть следующим образом:
#include <iostream>
#include <cstdlib>
#include <ctime>
int main()
{
const size_t N = 10;
double a[N];
std::srand( ( unsigned int )std::time( nullptr ) );
int MAX_VALUE = 9;
for ( auto &item : a ) item = 1 + std::rand() % MAX_VALUE;
for ( const auto &item : a ) std::cout << item << ' ';
std::cout << '\n';
double min = a[0];
size_t count = 1;
// preliminarily calculating the sum of all elements of the array
// used in the if ( count > 1 ) code block to escape a redundant loop
double sum = a[0];
for ( size_t i = 1; i < N; i++ )
{
sum += a[i];
if ( a[i] < min )
{
min = a[i];
count = 1;
}
else if ( not( min < a[i] ) )
{
++count;
}
}
if ( count > 1 )
{
double average = sum / N;
for ( auto &item : a )
{
if ( item == min ) item = average;
}
}
for ( const auto &item : a ) std::cout << item << ' ';
std::cout << '\n';
return 0;
}
Желательно перед циклом, который вычисляет сумму элементов, поместить комментарий, объясняющий, почему мы решили сделать это имеено в этом месте программы.
Собственно, я это все сделал, однако хочу оптимизировать код, чтобы было меньше строк.
Разделите ваш код на функции, после чего будет видно где требуется провести оптимизацию.
#include <iostream>
// В (double array[]) и (double * array) - эквивалентные записи.
void fillArray(double * array)
{
//Заполнить массив
...
}
void showArray(double * array)
{
// Отобразить массив
}
double arichmeticAverage(double * array)
{
double average = 0;
//Найти среднее арифметическое
...
return average;
}
double minNumber (double * array)
{
double min = 0;
//Поиск минимально значения
...
return min;
}
double something (double * array)
{
// Something
return ...;
}
int main()
{
double array[100];
fillArray(array);
showArray(array);
double average = arichmeticAverage(array);
double min = minNumber(array);
...
...
return 0;
}
Вот вам с двумя циклами. Учитесь пользоваться контейнерами, с ними и ошибок меньше и код получается проще. Можно было бы конечно обойтись и без них, но код получился бы намного сложнее и если не писать свой список, то пришлось бы добавлять ещё один массив того же размера что и исходный (это хорошо у вас 10 элементов... а если 10 тысяч? :) )
#include <iostream>
#include <iomanip>
#include <ctime>
#include <array>
#include <list>
#include <cmath>
#include <windows.h>
int main()
{
SetConsoleOutputCP(1251);
const int arraySize = 10;
srand(static_cast<unsigned>(time(nullptr)));
std::array<double, arraySize> dataArray; // исходный массив
double minNumber = 1e9; // инициализируем заведомо бОльшим значением
double average = 0.0;
double currentData; // просто для ускорения работы
std::list<unsigned> indexes; // список индексов минимальных чисел
std::cout << "Исходный массив:" << std::endl;
for (unsigned i = 0; i < dataArray.size(); i++) {
currentData = 1 + rand() % 9; // генерируем случайное число от 1 до 9
dataArray[i] = currentData; //Заполнение массива
std::cout << std::setprecision(2) << currentData << ' '; // выводим массив
if (minNumber > currentData) {
minNumber = currentData; // нашли новый минимум
indexes.clear(); // очищаем ранее найденные индексы минимума
indexes.push_back(i); // запоминаем индекс нового минимума
}
// далее можно было бы поставить обычное равенство, но с вещественным числами лучше поступать примерно так:
else if (fabs(minNumber-currentData)<1e-9) {
// нашли ещё один элемент с текущим минимумом
indexes.push_back(i);
}
average += currentData; // внутри цикла только накапливаем, проверка заполнения не нужна
}
// среднее значение получаем после цикла
average /= dataArray.size();
std::cout << std::endl << "Минимальное значение: "
<< std::setprecision(2) << minNumber << std::endl;
// теперь меняем массив и сразу печатаем
std::cout << "Измененный массив:" << std::endl;
for (unsigned i = 0; i < dataArray.size(); i++) {
if (i == indexes.front()) { // текущий элемент массива - минимум?
dataArray[i] = average; // меняем его
indexes.pop_front(); // удаляем изменённый элемент из списка индексов
}
std::cout << std::setprecision(2) << dataArray[i] << ' '; // выводим массив
}
std::cout << std::endl;
system("pause");
return 0;
}
Ну, например, вот через два цикла(как вы хотели)
double array[10];
size_t quantity = 0;
// тут инициализируем array[0]
double minNumber = array[0], average = array[0];
for (int i = 1; i < 10; ++i) {
// инициализируем array[i]
average += array[i];
if (minNumber > array[i])
minNumber = array[i];
}
for (int i = 0; i < 20; ++i) {
if (i >= 10 ) {
if (quantity < 2)
break;
printf("%.2f ", array[i % 10]);
}
else if ( array[i] == minNumber) {
++quantity;
array[i] = average / 10;
}
}
p.s. если ваш массив будет содержать целые, то вам нужен массив для типов int, а не double
Основные этапы разработки сайта для стоматологической клиники
Продвижение своими сайтами как стратегия роста и независимости