Самый большой и маленький из четырех целых чисел (без массивов, никаких функций, наименьших "если" )

Видите ли, я сам учу себя С++ (не совсем, я все еще откладываю -_-). Итак, теперь я начал университет, и они обучают C, и они заставили нас сделать программу ввода четырех целых чисел, и мы должны рассказать о самых больших и маленьких из них. Простой, нет?

Дело в том, что у меня уже есть хорошее понимание функций и массивов. Да, я МОГУ программировать это в массивах, без проблем. Но поскольку это была первая лаборатория, мы еще не "научились", поэтому я не могу использовать ни один из них, это было бы очень просто с этим.

Это то, что я там написал (он как-то чувствует себя не так).

#include<stdio.h>

int main(void)
{
    int first, second, third, fourth;
    printf("Enter four integers (separated by space): ");
    scanf("%d %d %d %d", &first, &second, &third, &fourth);

    if((first>second) && (first>third) && (first>fourth))
        printf("\nFirst number is largest");
    else if((second>first) && (second>third) && (second>fourth))
        printf("\nSecond number is largest");
    else if((third>second) && (third>first) && (third>fourth))
        printf("\nThird number is largest");
    else if((fourth>second) && (fourth>third) && (fourth>first))
        printf("\nFourth number is largest");

    if((first<second) && (first<third) && (first<fourth))
        printf("\nFirst number is smallest");
    else if((second<first) && (second<third) && (second<fourth))
        printf("\nSecond number is smallest");
    else if((third<second) && (third<first) && (third<fourth))
        printf("\nThird number is smallest");
    else if((fourth<second) && (fourth<third) && (fourth<first))
        printf("\nFourth number is smallest");

    printf("\n"); 
    return 0;
}

Как вы можете видеть, он слишком длинный, скучный и сложный. Но, увидев, что все, что мы рассмотрели в классе на данный момент, это циклы и решения. Есть ли более элегантный способ сделать это? Тот, который использует меньше if s? Не то, чтобы с этим что-то не так, но это может быть лучше.

P.S. Это не совсем "домашнее задание" или что-то еще. Я сделал программу, я просто хотел узнать, что я мог сделать, чтобы сделать ее лучше, и изучить лучшие методы программирования.

Ответы

Ответ 1

В соответствии с условием OP

Но, увидев, что все, что мы рассмотрели в классе, на данный момент, это циклы и решения. Есть ли более элегантный способ сделать это? Тот, который использует меньше if s?

Только одна команда if и один else if и один цикл for могут выполнить эту задачу. Простой и короткий!

#include <stdio.h>

int main()
{
    int num, max, min;

    printf ("Enter four numbers: ");
    scanf ("%d", &num);
    max = min = num;

    for (int i = 0; i < 3; i++)
    { 
        scanf ("%d", &num);
        if (max < num)
            max = num;
        else if (min > num)
            min = num;
    }

    printf ("The smallest and largest of given four numbers are %d and %d respectively.\n", min,  max);
    return 0;
}

Ответ 2

Попробуйте что-то вроде этого

int main(void) {
    int a=-2,b=-3,c=-4,d=-5;
    int max=a,min=a;

    if(b>max){
        max=b;
    }else if(b<min){
        min=b;
    }
    if(c>max){
        max=c;
    }else if(c<min){
        min=c;
    }
    if(d>max){
        max=d;
    }else if(d<min){
        min=d;
    }
    printf("max: %d min : %d",max,min);
    return 0;
}

Демо

Ответ 3

Сделайте "ручной" сортировку слияния или, ну, только второй бит:

Концептуально сортировка слияния работает следующим образом

  • Разделите несортированный список на n подписок, каждый из которых содержит 1 элемент (список из 1 элемента считается отсортированным).
  • Неоднократно слияние подписок для создания новых подсписок до тех пор, пока не останется только 1 подсписок. Это будет отсортированный список.

Merge sort merging step illustration

код:

int a = 5, b=4, c=7, d=9;
int min_ab, min_bc, min;
min_ab = a < b ? a : b;
min_bc = c < d ? b : c;
min = min_ab < min_bc ? min_ab : min_bc;
printf("%d", min);

.. и аналогично при max

Если вы предпочитаете, вы можете развернуть тернарный оператор на if (a < b) { min_ab = a; } else { min_ab = b; } (разброс по нескольким строкам для удобства чтения).

Сортировка слияния имеет сложность O(n*log(n)), поэтому вам больше не нужно O(n*log(n)) if (см. статью статьи в википедии о сортировке слияния). Согласно Википедии, "... все это сортировочные сорта и поэтому не могут работать лучше, чем O (n log n) в среднем или худшем случае" (источник), поэтому я думаю, что это не должно быть слишком далеко с точки зрения минимального количества if s. Хотя вы могли бы попытаться увидеть, приведет ли вручную выполнение одного из других алгоритмов к меньшему числу if; -).

Ответ 4

Вся проблема в классе, которая требует поиска самого большого и самого маленького одновременно, - научить вас извлекать максимальную ценную информацию из каждого сравнения.

Например, если вы знаете, что a > b истинно, из этого единственного сравнения вы должны понимать, что a больше не является кандидатом для самого маленького и больше не должен участвовать в каких-либо сравнениях, посвященных поиску самых маленьких. И в то же время вы должны понимать, что b больше не является кандидатом для самого большого. С 4 номерами два теста a > b и c > d уже четко разделяют числа на два независимых класса: два кандидата для самого большого и два кандидата для наименьшего. Остальное просто.

Другими словами, вся идея состоит в том, чтобы найти экстремальные значения параллельно, используя информацию, предоставленную каждым сравнением, для дальнейшей задачи поиска как самого маленького, так и самого большого значения.
if (first > second) { 
  int t = first; first = second; second = t; 
}

if (third > fourth) { 
  int t = third; third = fourth; fourth = t; 
}

/* Now 'first' and 'third' are candidates for the smallest,
   while 'second' and 'fourth' are candidates for the largest */

int min = first < third ? first : third;
int max = second > fourth ? second : fourth;

Как вы можете видеть, для поиска обоих чисел требуется только четыре сравнения.

Обратите внимание, что приведенный выше код дает вам значения самого маленького и самого большого, но он не говорит вам об исходном "индексе" числа, которое предоставило каждое значение. Не сразу понятно, действительно ли это необходимо. Текст вашего вопроса ничего не говорит об этом, в то время как предоставленный вами образец кода реализует его. В любом случае нетрудно обновить приведенный выше код, чтобы он "отслеживал" происхождение чисел.

Ответ 5

Это слишком просто, учитывая, что числа - это a, b, c, d:

#define min(a,b)  ((a) < (b) ? (a) : (b))
#define max(a,b)  ((a) > (b) ? (a) : (b))
biggest  = max (max(a,b), max(c,d))
smallest = min (min(a,b), min(c,d))

Здесь вы идете, нет утверждений, никаких функций (хотя последнее является самым глупым и вредным для адептов, о котором я когда-либо слышал).

Ответ 6

Вот решение с no if или elseif или функцией или макросом, но вместо этого используйте бит-сдвиг и вычитание; используя только один цикл для:

#include <stdio.h>
int main(){

  int num , max, min;

  printf("Enter four numbers: ");
  scanf("%d", &num);
  max = min = num;

  for(int i = 0; i < 3; i++)
  { 
    scanf("%d", &num);
    max = max * (1 - ( (max-num) >> 31) )
        + num *      ( (max-num) >> 31);
    min = min * (1 - ( (num-min) >> 31) )
        + num *      ( (num-min) >> 31);
  }

  printf("\n%d %d", max, min);
  return 0;
}

Операция (max-num) >> 31) фиксирует знак разницы, который при умножении на второе число дает минимальное значение сравнения.

Это происходит из старого кода SQL с тех пор, как на этом языке была построена конструкция CASE WHEN.

Ответ 7

Одной из идей может быть вычисление максимума и минимума первых двух чисел. Затем вы сравниваете остальные числа в парах. Большая одна из каждой пары сравнивается с максимальным током, а меньшая из каждой пары сравнивается с текущим минимумом. Таким образом, вы выполняете 3 сравнения для каждых 2 элементов, что немного более эффективно, чем ответ Arpit (2 сравнения для каждого элемента).

В коде:

#include <stdio.h>

int main(int argc, char **argv) {
    int a, b, c, d;
    printf("Enter four integers (separated by space): ");
    scanf("%d %d %d %d", &a, &b, &c, &d);

    int max, min;
    if (a > b) {
       max = a;
       min = b;
    }
    else {
       max = b;
       min = a;
    }

    if (c > d) {
       if (c > max) {
          max = c;
       }
       if (d < min) {
          min = d;
       }
    }
    else {
       if (d > max) {
          max = d;
       }
       if (c < min) {
          min = c;
       }
    }
    printf("max = %d, min = %d\n", max, min);
    return 0;
}

Ответ 8

Это код C имеет только 4 оператора if. Он перемещает максимальное число в позицию d и минимальное число в позицию. Значения b и c неправильно упорядочены в последовательности, но поскольку требования требуют минимального и максимального значения, этот код завершает задание:

#include <stdio.h>


    int main() {
        int a, b, c, d, temp;
        printf("Enter four digits: ");
        scanf("%d %d %d %d", &a, &b, &c, &d);
        if ( a > b){
            temp = a; a = b ; b = temp;
        }
        if ( c > d){
            temp = c; c = d ; d = temp;
        }
        if ( b > d ){
            temp = b; b = d; d = temp;
        }
        if ( a > c){
            temp = a; a = c ; c = temp;
        }
        printf("Max %d\nMin %d\n", d, a);

        return 0;
    }

Ответ 9

 Please have at the following    

 private int GetLargerValue(int num1, int num2, int num3, int num4)
            {
                int largeValue = 0;
                if (num1 > num2)
                {
                    if (num1 > num3)
                        largeValue = (num1 > num4) ? num1 : num4;
                    else
                        largeValue = (num3 > num4) ? num3 : num4;

                }
                else if (num2 > num3)
                    largeValue = (num2 > num4) ? num2 : num4;
                else
                    largeValue = (num3 > num4) ? num3 : num4;

                return largeValue;
            }

Ответ 10

int max_of_four(int a, int b, int c, int d){
        int res=a;
        if(b/res)
            res=b;
        if(c/res)
            res=c;
        if(d/res)
            res=d;
        return res;
    }
int main() {
    int a, b, c, d;
    scanf("%d %d %d %d", &a, &b, &c, &d);
    int ans = max_of_four(a, b, c, d);
    printf("%d", ans);

    return 0;
}

Ответ 11

Для абсолютной производительности, т.е. Минимальные сравнения и задания.

Комментарии на каждом уровне показывают значения для кандидата min и max. Идея состоит в том, чтобы уменьшить наборы на каждом уровне, пока для каждого набора не будет только одного элемента. Это можно сделать только с 4 сравнениями и двумя присваиваниями.

        // min = a b c d
        // max = a b c d
        if (a <= b)
        {
            // min = a c d
            // max = b c d
            if ( c <= d){
                // min = a c
                // max = b d
                min = a <= c ? a : c;
                max = b > d ? b : d;
            }else{
                // min = a d
                // max = b c
                min = a <= d ? a : d;
                max = b > c ? b : c;
            }
        }
        else
        {
            // min = b c d
            // max = a c d
            if ( c <= d){
                // min = b c
                // max = a d
                min = b < c ? b : c;
                max = a > d ? a : d;
            }else{
                // min = b d
                // max = a c
                min = b < d ? b : d;
                max = a > c ? a : c;
            }
        }

Ответ 12

Я видел этот ответ, который использовался для утверждения цикла и if else, однако я опубликую решение, которое, как я полагаю, будет работать быстрее и будет использовать только четыре переменные. Итак, вот оно...

#include<stdio.h>
void main()
{
int a,b,c,d;
printf("Enter four numbers of your choice");
scanf("%d%d%d%d",&a,&b,&c,&d);
a>b&&a>c?a>d?printf("%d",a):printf("%d" ,d):(b>c&&b>d)?printf("%d",b):c>d?printf("%d", c):printf("%d",d);
}