2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




Начать новую тему Ответить на тему На страницу 1, 2  След.
 
 Найти среднее (С++)
Сообщение13.01.2019, 11:49 


06/04/18
228
Из трёх попарно неравных введённых пользователем целых чисел найти такое, которое не будет ни наибольшим, ни наименьшим.
код: [ скачать ] [ спрятать ]
Используется синтаксис C++
#include <iostream>
using namespace std;

int abc(int x, int y)
{
    return (x==y)? 0 : 1;
}

int xyz(int x, int y, int z)
{
    if ((x<y && y<z)||(x>y && y>z)) return y;
    else if ((y<x && x<z)||(y>x && x>z)) return x;
    else return z;
}

int main()
{
    int a, b, c;
    point:
    cout << "Введите три попарно неравных целых числа:\n";
    cin >> a >> b >> c;
    if (abc(a,b)*abc(a,c)*abc(b,c)==0) {cout << "Введено неверно\n";
    goto point;}
    else cout << xyz(a,b,c);
}
Хорошее ли у меня получилось решение? Если нет, то как можно сделать лучше?

 Профиль  
                  
 
 Re: Найти среднее (С++)
Сообщение13.01.2019, 12:06 
Аватара пользователя


14/12/17
723
деревня Инет-Кельманде
названия abc(), xyz() - почему не dura1(), dura2()?
abc() лучше бы проверял все три числа на равенство: return (x==y) || (x==z) || (y==z); - а не *, есть bool и есть || !!
xyz() можно упростить: if (x<y) return y<z ? y : z; else return x<z ? x : z;
или в одном стиле:
return x<y
? (y<z ? y : z)
: (x<z ? x : z);

 Профиль  
                  
 
 Re: Найти среднее (С++)
Сообщение13.01.2019, 12:12 
Заслуженный участник
Аватара пользователя


28/07/09
1111
Вызов функци abc(x, y) заменить конструкцией (x != y)

goto заменить на while.

Количество сравнений в основной функции явно можно уменьшить

 Профиль  
                  
 
 Re: Найти среднее (С++)
Сообщение13.01.2019, 12:17 


06/04/18
228
eugensk в сообщении #1368211 писал(а):
if (x<y) return y<z ? y : z;
Ну, проверьте случай z=1, x=2, y=3.

 Профиль  
                  
 
 Re: Найти среднее (С++)
Сообщение13.01.2019, 12:23 
Аватара пользователя


14/12/17
723
деревня Инет-Кельманде
Qlin в сообщении #1368214 писал(а):
Ну, проверьте случай z=1, x=2, y=3.

отлично! я слишком упростил и ошибся, значит истина где-то посередине. У вас 8 сравнений в xyz(), у меня 3, мне кажется, что достаточно 5.

 Профиль  
                  
 
 Re: Найти среднее (С++)
Сообщение13.01.2019, 12:33 


06/04/18
228
Legioner93 в сообщении #1368213 писал(а):
goto заменить на while.
Я бы это сделал, но если условие цикла выполнено, надо как-то информировать юзера, что введенные значения не подходят.
eugensk в сообщении #1368217 писал(а):
У вас 8 сравнений в xyz(), у меня 3, мне кажется, что достаточно 5.
Legioner93 в сообщении #1368213 писал(а):
Количество сравнений в основной функции явно можно уменьшить
Видимо можно. Но я не придумал, как.

 Профиль  
                  
 
 Re: Найти среднее (С++)
Сообщение13.01.2019, 12:36 
Заслуженный участник
Аватара пользователя


28/07/09
1111
Пузырёк вручную и выводим второй элемент
Код:
#include <cstdio>                                                               
                                                                                                                                                               
int xyz(int x, int y, int z)                                                   
{                                                                               
    if(x > y) swap(x, y);                                                       
    if(y > z) swap(y, z);                                                       
    if(x > y) swap(x, y);                                                       
    return y;                                                                   
}

 Профиль  
                  
 
 Re: Найти среднее (С++)
Сообщение13.01.2019, 12:45 


27/08/16
5107
Это называется не "среднее", а "медиана".

 Профиль  
                  
 
 Re: Найти среднее (С++)
Сообщение13.01.2019, 12:47 
Аватара пользователя


14/12/17
723
деревня Инет-Кельманде
Точно 5 сравений в коде:

Используется синтаксис C++
return x<y
         ? (y<z  
            ? y                 // x<y y<z
            : (x<z ? z : x))    // x<y z<y
         : (x<z
            ? x                 // y<x x<z
            : (y<z ? z : y));   // y<x z<x
 


Осуществляются или 2, или 3, эффективнее сделать уже не получится.

 Профиль  
                  
 
 Re: Найти среднее (С++)
Сообщение13.01.2019, 12:48 


06/04/18
228
Legioner93, да, этот вариант хорош. Спасибо.

Поскольку от goto принято избавляться, я перепишу определение функции main:
Используется синтаксис C++
int main()
{
    int a, b, c;
    cout << "Введите три попарно неравных целых числа:\n";
    cin >> a >> b >> c;
    while ((a==b)||(b==c)||(a==c))
    {
    cout << "Введено неверно\n";
    cout << "Введите три попарно неравных целых числа:\n";
    cin >> a >> b >> c;
    }
    cout << xyz(a,b,c);
}

 Профиль  
                  
 
 Re: Найти среднее (С++)
Сообщение13.01.2019, 12:54 
Заслуженный участник
Аватара пользователя


28/07/09
1111
Код:
int xyz(int x, int y, int z)                                                   
{                                                                               
    return max(min(x, y), min(max(x, y), z));                                   
}


-- Вс янв 13, 2019 13:05:19 --

Qlin
Можно избежать дублирования ввода и вывода, и при этом обойтись без goto

Код:
int main()                                                                     
{                                                                               
    int a, b, c;                                                               
    do                                                                         
    {                                                                           
        cout << "Введите три попарно неравных целых числа:\n";                 
        cin >> a >> b >> c;                                                     
    }                                                                           
    while(((a==b)||(b==c)||(a==c)) && (cout << "Введено неверно\n"));           
    cout << xyz(a,b,c);                                                         
}


Кстати, лучше не используйте cout << "Text\n", вместо этого cout << "Text" << endl

 Профиль  
                  
 
 Найти среднее
Сообщение13.01.2019, 13:36 
Аватара пользователя


10/10/18
394
At Home
Используется синтаксис C++
int mid( int a, int b, int c )
{
  switch( (a<b)*4 + (b<c)*2 + (a<c)*1 )
  {
  case 0: return b; // 000: a>b, b>c, a>c
  case 1: return 0; // 001: a>b, b>c, a<c: cannot be
  case 2: return c; // 010: a>b, b<c, a>c
  case 3: return a; // 011: a>b, b<c, a<c
  case 4: return a; // 100: a<b, b>c, a>c
  case 5: return c; // 101: a<b, b>c, a<c
  case 6: return 0; // 110: a<b, b<c, a>c: cannot be
  case 7: return b; // 111: a<b, b<c, a<c
  }
}
Такой switch компилятор оптимизирует в jmp.
То есть, условные переходы в функции — отсутствуют.
Всех — по паре, да ещё и симметрично относительно центральной горизонтали (между 3 и 4).

 Профиль  
                  
 
 Re: Найти среднее (С++)
Сообщение13.01.2019, 14:07 


06/04/18
228
Legioner93 в сообщении #1368224 писал(а):
Используется синтаксис C++
while(((a==b)||(b==c)||(a==c)) && (cout << "Введено неверно\n"));
Я понимаю, что (cout << "Введено неверно\n") — это тоже своего рода выражение. Но какое оно возвращает значение? Как повлияет на выполнение цикла?

 Профиль  
                  
 
 Re: Найти среднее (С++)
Сообщение13.01.2019, 14:18 
Аватара пользователя


14/12/17
723
деревня Инет-Кельманде
Раз можно написать cout << "Введено неверно\n" << ...., то видимо cout << "Введено неверно\n" возвращает сам себя, cout.
Далее, operator bool() для cout (в условии будет вызываться именно он) - это скорее всего признак отсутствия ошибки, то есть программа может выйти из цикла, если первое условие все еще true, но cout почему-то сломался, не смог вывести приглашение и вернул false, и тогда xyz() выполнится для равных чисел. Не знаю, мне кажется лучше добавить , true к cout в условии:

while(((a==b)||(b==c)||(a==c)) && ((cout << "Введено неверно\n"), true));

 Профиль  
                  
 
 Re: Найти среднее
Сообщение14.01.2019, 15:31 
Экс-модератор
Аватара пользователя


23/12/05
10988
SergeCpp в сообщении #1368235 писал(а):
Используется синтаксис C++
int mid( int a, int b, int c )
{
  switch( (a<b)*4 + (b<c)*2 + (a<c)*1 )
  {
 ...
  }
}
Такой switch компилятор оптимизирует в jmp.
То есть, условные переходы в функции — отсутствуют.
Всех — по паре, да ещё и симметрично относительно центральной горизонтали (между 3 и 4).

1) Для бОльшей наглядности сложения можно заменить на |.
2) Статический анализатор может обругать такой код, сказав, что не все пути имеют return. Чтобы его удовлетворить, можно добавить поле default или воткнуть return за switch-ем.
3) Нулевое возвращаемое значение является вполне корректным для данной функции - не очень красиво писать его в return без какой-либо дополнительной обработки, даже если программа туда никогда не зайдет. Кстати, а зачем выписывать варианты, которые не могут случиться?

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 24 ]  На страницу 1, 2  След.

Модераторы: Karan, PAV, Toucan, maxal, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group