Как найти большее число без сравнения

Найти большее значение без сравнения и условий

Время на прочтение
1 мин

Количество просмотров 8.6K

Даны 2 целых числа: a и b. Например, a=3, b=6.

Напишите выражение, которое будет находить большее число (a или b), без условий и сравнений. Чисто математика (модули, например, можно).

Правильное решение в комментариях, аккуратно! :)

Самый распространенный вариант реализации функции max — проверка знака выражения a - b. В этом случае мы не можем использовать оператор сравнения, но можем использовать умножение.

Примечание Смысл задачи не в том, чтобы скрыть сравнение или условие в какую-нибудь стандартную функцию типа abs() или стандартный оператор типа целочисленного деления, а в том, чтобы всё это сделать вообще без инструкций ветвления на уровне процессора.

Обозначим знак выражения a - b как k. Если a - b >= 0, то k = 1, иначе k = 0. Пусть q будет инвертированным значением k.

Код будет иметь вид:

/* Отражаем 1 в 0 и 0 в 1 */
int flip(int bit) {
	return 1^bit;
}

/* Возвращаем 1, если число положительное, и 0, если отрицательное*/
int sign(int a) {
	return flip((a >> (sizeof(int) * CHAR_BIT - 1)))) & 0x1);
}

int getMaxNaive(int a, int b) {
	int k = sign(a - b);
	int q = flip(k);
	return a * k + b * q;
}

Это почти работоспособный код (можете проверить). Проблемы начинаются при переполнении. Предположим, что a = INT_MAX - 2 и b = -15. В этом случае a - b перестанет помещаться в INT_MAX и вызовет переполнение (значение станет отрицательным).

Можно использовать тот же подход, но придумать другую реализацию. Нам нужно, чтобы выполнялось условие k = 1, когда a > b. Для этого придется использовать более сложную логику.

Когда возникает переполнение a - b? Только тогда, когда a положительное число, а b отрицательное (или наоборот). Трудно обнаружить факт переполнения, но мы в состоянии понять, что a и b имеют разные знаки. Если у а и b разные знаки, то пусть k = sign(a).

Логика будет следующей:

1. если у a и b разные знаки:
// если a > 0, то b < 0 и k = 1.
// если a < 0, то b > 0 и k = 0.
// так или иначе, k = sign(a)
2. пусть k = sign(a)
3. иначе пусть k = sign(a - b) // переполнение невозможно

Приведенный далее код реализует этот алгоритм, используя умножение вместо операторов сравнения (проверить):

int getMax(int a, int b) {
	int c = a - b;
	
	int sa = sign(a); // если a >= 0, то 1, иначе 0
	int sb = sign(b); // если a >= 1, то 1, иначе 0
	int sc = sign(c); // зависит от переполнения a - b
	
	/* Цель: найти k, которое = 1, если а > b, и 0, если a < b.
	 * если a = b, k не имеет значения */

	// Если у а и b равные знаки, то k = sign(a)
	int use_sign_of_a = sa ^ sb;
	
	// Если у a и b одинаковый знак, то k = sign(a - b)
	int use_sign_of_c = flip(sa ^ sb);
	
	int k = use_sign_of_a * sa + use_sign_of_c * sc;
	int q = flip(k); // отражение k

	return a * k + b * q;
}

Отметим, что для большей наглядности мы разделяем код на методы и вводим переменные. Это не самый компактный или эффективный способ написания кода, но так мы делаем код понятнее.

Разбор взят из книги Гейл Л. Макдауэлл «Cracking the Coding Interview» (есть в переводе).

Is it possible to find the greatest of two integers without any comparison? I found some solutions:

if(!(a/b)) // if a is less than b then division result will be zero.
{
    cout << " b is greater than a";
}
else if (!(a-b)) // we know a is greater than or equal to b now.  check whether they are equal.
{
    cout << "a and b are equal";
}
else
    cout << "a is greater than b";

But if(c) or if(!c) is a comparison to zero. In addition it doesn’t work for negative numbers. In fact I need a solution that avoids any if statement. Instead I should use switch statements and arithmetic operators. ThanX.

gsamaras's user avatar

gsamaras

71.6k44 gold badges188 silver badges299 bronze badges

asked Jan 24, 2009 at 22:37

Ameer Jewdaki's user avatar

Ameer JewdakiAmeer Jewdaki

1,7484 gold badges21 silver badges36 bronze badges

4

Here’s a fun bit-twiddling version that doesn’t have any conditional branches.

int g = (int)"greater";
int l = (int)"less";
int e = (int)"equal";

int a = 7;
int b = 10;

char *result = (char*)((((a - b) >> 31) & l) | (((b - a) >> 31) & g) | ((~((a - b) | (b - a))) >> 31) & e);
cout << result;

answered Jan 24, 2009 at 23:32

Eclipse's user avatar

You might exploit the fact that the sign of the calculation a - b depends on which number is greater. This is used in many implementations of comparison. But I believe you’ll never be able to completely avoid comparison. In this case, you still at least need to evaluate the contents of the sign flag on the processor.

If you just need to display the lower number you can also use arithmetic tricks:

result = ((a + b) - sqrt((a - b) * (a - b))) / 2

EDIT erm … you’re allowed to use switch?

I should use switch statements and arithmetic operators.

switch is basically the same as chained if and as such it also uses comparison. This sounds as if you should indeed just compare to zero to see what sign a - b has.

answered Jan 24, 2009 at 22:58

Konrad Rudolph's user avatar

Konrad RudolphKonrad Rudolph

526k130 gold badges930 silver badges1208 bronze badges

Not one of the samples presented in the question or any of the answers thus far protects from division by zero. Why on earth are you trying to avoid an ‘if’ statement? I suspect homework question about ?: operators.

cout << "Maximum is: " << ((a>b)?a:b)

There we go.

It’s not possible to compare two numbers without a comparison. You can fudge it and do an indirect operation, but at the end of the day you’re comparing something. Trust the compiler to optimize the code and select the best operations.

answered Jan 24, 2009 at 22:55

Adam Hawes's user avatar

Adam HawesAdam Hawes

5,4411 gold badge23 silver badges30 bronze badges

1

As a pointless exercise, here’s a way of implementing a cond function — to serve the purpose of if, supposing it (and switch, and ?:) had somehow disappeared from the language, and you’re using C++0x.

void cond(bool expr, std::function<void ()> ifTrue, std::function<void ()> ifFalse)
{
    std::function<void ()> choices[2] = { ifTrue, ifFalse };
    choices[expr == false]();
}

e.g.

cond(x > y,
    /*then*/ [] { std::cout << "x is greater than y"; },
    /*else*/ [] { std::cout << "x is not greater than y"; });

Like I say, pointless.

answered Jan 25, 2009 at 0:43

Daniel Earwicker's user avatar

Daniel EarwickerDaniel Earwicker

115k38 gold badges205 silver badges283 bronze badges

5

char c;
c=0x3D + (!(b/a) && (a-b)) - (!(a/b) && (a-b));
printf("a %c b",c);

Baum mit Augen's user avatar

answered Jan 24, 2009 at 23:21

(!(a/b) ?  cout << " b is greater than a" : (!(b-a) ? cout << "a and b are equal" :  cout << "a is greater than b") :  cout << "a is greater than b");

That gets a bit messy though

Edit: Is this homework?

answered Jan 24, 2009 at 22:41

fmsf's user avatar

fmsffmsf

36.1k48 gold badges147 silver badges194 bronze badges

2

I just cant see any good reason to do that : who would want to program without «if» ?

a possible answer is :

( ( a + b ) + abs ( a -b ) ) / 2

I guess «abs» just hides a «if» somewhere, just as the ternary operator that is just another name for «if» …

answered Jan 24, 2009 at 22:51

siukurnin's user avatar

siukurninsiukurnin

2,83217 silver badges20 bronze badges

1

The Perverse Idea: use an array of function pointers. Then with some arithmetic and bitwise operations get an index into that array.

answered Jan 24, 2009 at 23:25

Vilx-'s user avatar

Vilx-Vilx-

104k86 gold badges277 silver badges420 bronze badges

Try this, tested it, works well.

public static int compare(int a, int b)
{
    int c = a - b;
    return (c >> 31) & 1 ^ 1;
}

Michael0x2a's user avatar

Michael0x2a

56.5k28 gold badges172 silver badges220 bronze badges

answered Oct 14, 2013 at 18:24

user2879961's user avatar

I think this method is better than others, you can use this logic c and java both programming languages but int should be of 4 byte if int is of 2 byte then make 15 byte right shift instead of 31 byte.

enter code here

#include<stdio.h>

main()
{
   int a, b;
   printf("Enter three numbersn");
   scanf("%d %d", &a, &b);
   printf("Largest number is %d n",findMax( a,b ));
}
int findMax( int x, int y)
{
  int z = x - y;
  int i  = (z  >>  31)  &  0x1;
  printf("i = %d shift = %d n", i, (z>>31));
  int  max  =  x - i  *  z;
  return max;
}

answered Jun 21, 2016 at 18:06

kumar arvind gupta's user avatar

To get the greatest number without using comparison/relational operator

void PrintGreatestNumber(int a, int b)
{
   int [] x = new int[] { -1, 0, 1 };
   int greatestNumber =  ((a+b)+ x[ 1 + ((a-b) >> 31) - (-(a-b) >> 31)] * (a-b)) /2;  
   Console.WriteLine(greatestNumber);
}

answered Mar 9, 2019 at 20:56

sudil ravindran pk's user avatar

You can use a function to check equal or not using xor bitwise operator.
here, you can write this function as:

int Check(int a, int b){
    return (a^b);
}

This function will return 0, if two integers are same, otherwise not.

Here, included an example to understand this function.

Let take two integers as a = 1, b= 2

the bits of 1 is —> 00000001
and for 2 is —> 00000010

if we apply xor operation here, we’ll get the result as 00000000 which is 0 in integer.
because the xor operations are:

1 xor 1 = 0
1 xor 0 = 1
0 xor 1 = 1
0 xor 0 = 0

Another way you can do by subtracting the number like

int Check(int a, int b)
{
   return abs(a-b);
}

The logic here will work as same as before. If we get 0 then it should be equal otherwise not!

answered Sep 14, 2020 at 18:33

Saqib's user avatar

SaqibSaqib

391 silver badge7 bronze badges

Assume X and Y are the two inputs.
X>Y will be: ((X+Y)+ abs(X-Y))/2 and
X<Y will be: ((X+Y)- abs(X-Y))/2

Now you can get abs() from #include<math.h>, it actually return the absolute value.

Cheers!

answered Dec 12, 2020 at 3:19

Soumyo Tarafder's user avatar

void greater(int a, int b) {
    int c = a - b;
    switch(c) {
        case 0:
            cout << "a and b are equal" << endl;
            break;
        default:
            int d = c & (1<<31);
            switch(d) {
                case 0:
                    cout << "a is bigger than b" << endl;
                    break;
                default:
                    cout << "a is less than b" << endl;
            }
    }
}

Termininja's user avatar

Termininja

6,53012 gold badges48 silver badges49 bronze badges

answered Jan 24, 2009 at 23:07

Ameer Jewdaki's user avatar

Ameer JewdakiAmeer Jewdaki

1,7484 gold badges21 silver badges36 bronze badges

1

Вычтите их и проверьте знак, используя отвратительные бит-скручивающие хаки
http://graphics.stanford.edu/~seander/bithacks.html

Не делайте этого в производственном коде, если другие программисты знают, где вы живете.

Martin Beckett
25 янв. 2009, в 00:54

Поделиться

Здесь интересная версия с двумя битами, которая не имеет условных ветвей.

int g = (int)"greater";
int l = (int)"less";
int e = (int)"equal";

int a = 7;
int b = 10;

char *result = (char*)((((a - b) >> 31) & l) | (((b - a) >> 31) & g) | ((~((a - b) | (b - a))) >> 31) & e);
cout << result;

Eclipse
24 янв. 2009, в 23:55

Поделиться

Ни один из образцов, представленных в вопросе, или любой из ответов до сих пор не защищает от деления на ноль. Почему вы пытаетесь избежать заявления «если»? Я подозреваю, что вопрос о домашнем задании?: Операторы.

cout << "Maximum is: " << ((a>b)?a:b)

Мы идем.

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

Adam Hawes
25 янв. 2009, в 00:27

Поделиться

char c
c = 0x3D + (! (b/a) && (a-b)) — (! (a/b) && (a-b))
printf ( «a% c b», c);

phy1729
25 янв. 2009, в 00:33

Поделиться

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

Если вам просто нужно отобразить меньшее число, вы также можете использовать арифметические трюки:

result = ((a + b) - sqrt((a - b) * (a - b))) / 2

EDIT erm… вам разрешено использовать switch?

Я должен использовать операторы switch и арифметические операторы.

switch в основном совпадает с цепочкой if и, как таковой, также использует сравнение. Это звучит так, как будто вы действительно должны просто сравнить с нолем, чтобы увидеть, какой знак a - b имеет.

Konrad Rudolph
24 янв. 2009, в 23:07

Поделиться

Я думаю, что этот метод лучше других, вы можете использовать эту логику c и java для обоих языков программирования, но int должен быть 4 байта, если int имеет 2 байта, тогда вместо 15 байт следует сдвинуть 15 байт вправо.

enter code here

#include<stdio.h>

main()
{
   int a, b;
   printf("Enter three numbersn");
   scanf("%d %d", &a, &b);
   printf("Largest number is %d n",findMax( a,b ));
}
int findMax( int x, int y)
{
  int z = x - y;
  int i  = (z  >>  31)  &  0x1;
  printf("i = %d shift = %d n", i, (z>>31));
  int  max  =  x - i  *  z;
  return max;
}

kumar arvind gupta
21 июнь 2016, в 18:46

Поделиться

Попробуйте это, проверив его, хорошо работает.

public static int compare(int a, int b)
{
    int c = a - b;
    return (c >> 31) & 1 ^ 1;
}

user2879961
14 окт. 2013, в 19:24

Поделиться

Как бессмысленное упражнение, здесь способ реализации функции cond — служить цели if, предполагая, что он (и switch и ?:) каким-то образом исчез с языка, а вы используя С++ 0x.

void cond(bool expr, std::function<void ()> ifTrue, std::function<void ()> ifFalse)
{
    std::function<void ()> choices[2] = { ifTrue, ifFalse };
    choices[expr == false]();
}

например.

cond(x > y,
    /*then*/ [] { std::cout << "x is greater than y"; },
    /*else*/ [] { std::cout << "x is not greater than y"; });

Как я говорю, бессмысленно.

Daniel Earwicker
25 янв. 2009, в 01:05

Поделиться

The Perverse Idea: используйте массив указателей на функции. Затем с некоторыми арифметическими и побитовыми операциями получают индекс в этот массив.

Vilx-
25 янв. 2009, в 00:34

Поделиться

Я просто не вижу причин для этого: кто захочет запрограммировать без «если»?

Возможный ответ:

((a + b) + abs (a -b))/2

Я думаю, что «abs» просто скрывает «if» где-то, как тернарный оператор, который является просто другим именем «if»…

siukurnin
25 янв. 2009, в 00:31

Поделиться

(!(a/b) ?  cout << " b is greater than a" : (!(b-a) ? cout << "a and b are equal" :  cout << "a is greater than b") :  cout << "a is greater than b");

Это становится немного грязным, хотя

Изменить: это домашнее задание?

fmsf
24 янв. 2009, в 23:55

Поделиться

void greater(int a, int b) {
    int c = a - b;
    switch(c) {
        case 0:
            cout << "a and b are equal" << endl;
            break;
        default:
            int d = c & (1<<31);
            switch(d) {
                case 0:
                    cout << "a is bigger than b" << endl;
                    break;
                default:
                    cout << "a is less than b" << endl;
            }
    }
}

Ameer Jewdaki
25 янв. 2009, в 00:12

Поделиться

Ещё вопросы

  • 1Выбор контактов в диалоге
  • 0Выберите двойным щелчком или одной буквой div, который делает фокус ввода
  • 1Java Custom enum
  • 0MySQL: mysqli_fetch_array ()
  • 1Что за выражение «throws» используется здесь, а что, если не используется?
  • 0общее количество просмотров продукта в magento
  • 1Копии файлов, скопированных в APK META-INF / android.arch.lifecycle_runtime.version
  • 1Подсчитать частичное совпадение в каждом столбце DataFrame в Pandas
  • 02 способа привязки данных не работает
  • 1FusedLocationProviderClient RemoveLocationUpdatesAsync Задача не выполнена
  • 0AngularJS: поделиться общей фабрикой для создания нового объекта
  • 1Можно ли проанализировать с JSONObject и RealmObject с той же моделью?
  • 0MySQL не может создать таблицу
  • 0Как работать с аргументами в Xcode
  • 1Robot Framework, расширяющий селен для обработки элемента нагрузки
  • 0обменивать переменные между страницей виртуальной клавиатуры на другую открытую страницу только в javascript (НЕ Jquery)?
  • 1Это неправильное использование синглтона?
  • 1Как установить права на тикет в клиентской библиотеке Zenpy python
  • 0Как использовать mysql после установки более старой версии mariadb через homebrew?
  • 0Как передать выбранные значения в JavaScript
  • 1Gensim Word2Vec выбирает второстепенный набор векторов слов из предварительно обученной модели
  • 0Оператор перегрузки >>
  • 0PHP заполнить выпадающий список с помощью jquery
  • 1У объекта ‘numpy.ndarray’ нет атрибута ‘fitness’
  • 0Добавление капчи в dform
  • 0Ошибка подключения к базе данных, статус HTTP 500
  • 1Регулярное выражение Javascript допускает только один знак плюс (+) в начале, а длина строки не должна превышать 15 символов
  • 0Создание анимированного макета 1-3 столбца с использованием Angular
  • 1indexOf и BufferedReader не работают для меня
  • 0Как получить выходные данные консоли в командной строке?
  • 0Как я могу вставить автоматически определенный день и определенное время в MySQL Вставить запрос
  • 1Открытие и закрытие компактного фреймворка мультиформного приложения
  • 0Как увеличить линию графика так же, как при наведении легенды, и автоматически сбросить ее при нажатии кнопки в старшей диаграмме?
  • 0#! / usr / bin / env php работает orm: schema-tool: create
  • 0Несоответствие строк при вызове ajax в WebApi
  • 1ExoPlayer не воспроизводит видео из необработанной папки в Kitkat
  • 0Модель Cakephp с несколькими статусами
  • 1Как сохранить состояние экземпляра фрагмента после использования replace ()?
  • 0Может ли str_shuffle вернуть не случайный результат?
  • 1преобразование строковых значений .csv в double
  • 1Шрифт C3.js tootltip
  • 0Добавить значение даты и времени
  • 1java.lang.NoSuchFieldError: имя во время выполнения в спящем проекте
  • 0Что такое динамический компоновщик в программировании?
  • 1Написать характеристику BLE без обнаружения сервисов Android
  • 1Как установить имя файла при загрузке файла? [Дубликат]
  • 0Объединить несколько таблиц MySQL
  • 1Вызов Java в XSL, неправильный тип параметра
  • 0Случайная непрозрачность анимации в списке элементов
  • 1Поворот холста и представление растрового изображения

В этой статье мы разберем, как найти наибольшее число из трех, а также как найти наибольшее число в целом списке чисел. Будем применять условия и встроенные функции max() и sort().

Как найти наибольшее число из трех введенных

Суть задачи: пользователем вводится три числа, и программа на Python должна найти наибольшее из них.

Допустим, у нас есть три числа: x, y и z. Пусть x = 2, y = 5 и z = 8. Очевидно, что наибольшее число из них это z. Давайте посмотрим, как мы сможем это определить при помощи Python. Разберем три способа.

Способ 1: условия и сравнения

def maximum(x, y, z):
    if (x >= y) and (x >= z):
        largest = x

    elif (y >= x) and (y >= z):
        largest = y

    else:
        largest = z

    return largest


print(maximum(2, 5, 8))


# Результат:
# 8

Два других способа связаны с применением встроенной функции max(), поэтому давайте познакомимся с ней.

Как работает встроенная функция max()

Функция max() в Python возвращает наибольшее число из переданных ей аргументов и имеет следующий синтаксис: max( x, y, z,..). Все параметры здесь являются числами. Примеры использования функции max():

print(max(70, 900, 3000))  # 3000

print(max(222, 45, 80))  # 222

print(max(70, 9040, 700))  # 9040

print(max(7022, 9020, 300))  # 9020

print(max(5555, 900, 6))  # 5555

Способ 2: использование функции max()

Функция max() прекрасно подходит для поиска наибольшего из трех чисел.

x = 2

y = 5

z = 8

print(max(x, y, z))


# Результат:
# 8

Метод max() также используется для нахождения наибольшего числа в списке.

Способ 3: помещение чисел в список и применение max()

Мы также можем найти наибольшее число при помощи списка. Сначала мы инициализируем три переменные x, y, z и добавляем их в список. Затем, используя функцию max(), мы можем получить наибольшее число из этого списка.

Например:

def maximum(x, y, z):
    list = [x, y, z]

    return max(list)


x, y, z = 2, 5, 8
print(maximum(x, y, z))


# Результат:
# 8

Чтобы найти наибольшее из некоторого количества чисел, можно сперва преобразовать имеющиеся числа в список (скажем, при помощи встроенной функции list()), а потом найти наибольшее число в списке. Далее у нас есть два пути: отсортировать список или применить уже известную нам функцию max().

Поиск наибольшего числа в списке при помощи функции sort()

Функция sort() по умолчанию сортирует массив в возрастающем порядке. Соответственно, последнее значение и будет наибольшим числом.

lis = [100, 43, 400, 63, 65]

lis.sort()

print("Largest number in the list is:", lis[-1])


# Результат:
# Largest number in the list is 400

Поиск наибольшего числа в списке при помощи функции max()

lis = [100, 43, 400, 63, 65]

print("Largest number in the list is:", max(lis))


# Результат:
# The largest number in the list is 400

Перевод статьи “Python Program to Find the Largest Among Three Numbers”.

Понравилась статья? Поделить с друзьями:

Не пропустите также:

  • Как найти кальян на авито
  • Как найти массу атома кальция
  • Как найти угнанный мотоцикл
  • Как найти папку документс
  • Как найти третью медиану если известны две

  • 0 0 голоса
    Рейтинг статьи
    Подписаться
    Уведомить о
    guest

    0 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии