Объясните этот фрагмент, который находит максимум два целых числа без использования if-else или любого другого оператора сравнения? - PullRequest
73 голосов
/ 23 января 2011

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

Пример Вход: 5, 10 Выход: 10

Я нашел это решение, может кто-нибудь помочь мне понять эти строки кода

int getMax(int a, int b) {  
    int c = a - b;  
    int k = (c >> 31) & 0x1;  
    int max = a - k * c;  
    return max;  
}

Ответы [ 19 ]

0 голосов
/ 02 марта 2019

// В C # вы можете использовать математическую библиотеку для выполнения функции min или max

с использованием System;

class NumberComparator {

static void Main()
{

    Console.Write(" write the first number to compare: ");
    double first_Number = double.Parse(Console.ReadLine());

    Console.Write(" write the second number to compare: ");
    double second_Number = double.Parse(Console.ReadLine());

    double compare_Numbers = Math.Max(first_Number, second_Number);
    Console.Write("{0} is greater",compare_Numbers);

}

}

0 голосов
/ 09 октября 2017

Вот пара битовых переворотов методов, чтобы получить максимум двух целых значений:

Метод 1

int max1(int a, int b) {
  static const size_t SIGN_BIT_SHIFT = sizeof(a) * 8 - 1;
  int mask = (a - b) >> SIGN_BIT_SHIFT;
  return (a & ~mask) | (b & mask);
}

Пояснение:

  • (a - b) >> SIGN_BIT_SHIFT - если a > b, то a - b положительно, поэтому бит знака равен 0, а маска - 0x00.00.В противном случае, a < b, поэтому a - b отрицателен, бит знака равен 1, и после сдвига мы получим маску 0xFF..FF
  • (маска & & -) - Если маска 0xFF..FF, тогда ~mask равно 0x00..00, а затем это значение равно 0.В противном случае ~mask равно 0xFF..FF, а значение равно a
  • (b & mask). Если маска 0xFF..FF, то это значение равно b.В противном случае mask равно 0x00..00, а значение равно 0.

Наконец:

  • Если a >= b, то a - b положительно, мы получаемmax = a | 0 = a
  • Если a < b, тогда a - b отрицательно, мы получаем max = 0 | b = b

Метод 2

int max2(int a, int b) {
  static const size_t SIGN_BIT_SHIFT = sizeof(a) * 8 - 1;
  int mask = (a - b) >> SIGN_BIT_SHIFT;
  return a ^ ((a ^ b) & mask);
}

Объяснение:

  • Объяснение маски такое же, как для Метод 1 .Если a > b маска 0x00..00, в противном случае маска 0xFF..FF
  • Если маска 0x00..00, тогда (a ^ b) & mask равна 0x00..00
  • Если маска0xFF..FF, тогда (a ^ b) & mask равно a ^ b

Наконец:

  • Если a >= b, мы получим a ^ 0x00..00 = a
  • Если a < b, получаем a ^ a ^ b = b
0 голосов
/ 26 мая 2017
#include<stdio.h>
main()
{
        int num1,num2,diff;
        printf("Enter number 1 : ");
        scanf("%d",&num1);
        printf("Enter number 2 : ");
        scanf("%d",&num2);
        diff=num1-num2;
        num1=abs(diff);
        num2=num1+diff;
        if(num1==num2)
                printf("Both number are equal\n");
        else if(num2==0)
                printf("Num2 > Num1\n");
        else
                printf("Num1 > Num2\n");
}
0 голосов
/ 18 июля 2016

Код, который я предоставляю, предназначен для поиска максимума между двумя числами, числа могут быть любого типа данных (целые, плавающие). Если введенные числа равны, то функция возвращает число.

double findmax(double a, double b)
{
    //find the difference of the two numbers
    double diff=a-b;
    double temp_diff=diff;
    int int_diff=temp_diff;
    /*
      For the floating point numbers the difference contains decimal
      values (for example 0.0009, 2.63 etc.) if the left side of '.' contains 0 then we need
      to get a non-zero number on the left side of '.'
    */
    while ( (!(int_diff|0)) && ((temp_diff-int_diff)||(0.0)) )
    {
       temp_diff = temp_diff * 10;
       int_diff = temp_diff;
    }
    /*
      shift the sign bit of variable 'int_diff' to the LSB position and find if it is 
      1(difference is -ve) or 0(difference is +ve) , then multiply it with the difference of
      the two numbers (variable 'diff') then subtract it with the variable a.
    */
    return a- (diff * ( int_diff >> (sizeof(int) * 8 - 1 ) & 1 ));
}

Описание

  • Первое, что функция принимает аргументы как double и имеет тип возвращаемого значения как double. Причина этого заключается в том, что для создания единой функции можно найти максимум для всех типов. Когда предоставляются целочисленные числа или одно является целым числом, а другое - с плавающей запятой, то также из-за неявного преобразования можно также использовать функцию для поиска максимума для целых чисел.
  • Основная логика проста, скажем, у нас есть два числа a & b, если ab> 0 (т. Е. Разница положительная), тогда a является максимальным, иначе, если ab == 0, тогда оба равны, и если ab <0 (т.е. diff is -ve) b - максимум. </li>
  • Знаковый бит сохраняется как самый старший бит (MSB) в памяти. Если MSB равен 1 и наоборот. Чтобы проверить, является ли MSB 1 или 0, мы сдвигаем MSB в позицию LSB и побитово & с 1, если результат равен 1, тогда число равно -ve, иначе нет. это + ве. Этот результат получается утверждением:

    int_diff >> (sizeof (int) * 8 - 1) & 1

Здесь, чтобы получить знаковый бит от MSB к LSB, мы сместим его вправо в k-1 бит (где k - количество битов, необходимых для сохранения целого числа в памяти, которое зависит от типа системы). Здесь k = sizeof (int) * 8, так как sizeof () дает количество байтов, необходимое для сохранения целого числа, чтобы получить no. битов, мы умножаем его на 8. После сдвига вправо мы применяем побитовое значение & с 1, чтобы получить результат.

  • Теперь после получения результата (допустим, что это r) равным 1 (для -ve diff) и 0 (для + ve diff), мы умножаем результат на разницу двух чисел, логика дано следующим образом:

    1. если a> b, то a-b> 0, т. Е. Равно + ve, поэтому результат равен 0 (т. Е. R = 0). Таким образом, a- (a-b) * r => a- (a-b) * 0, что дает «a» как максимум.
    2. если a a- (a-b) * 1 => a-a + b => b, что дает «b» как максимум.
  • Теперь есть две оставшиеся точки: 1. использование цикла while и 2. почему я использовал переменную int_diff в качестве целого числа. Чтобы ответить на них правильно, мы должны понимать некоторые моменты:

    1. Значения плавающего типа не могут использоваться в качестве операнда для побитовых операторов.
    2. По вышеуказанной причине нам нужно получить значение в целочисленном значении, чтобы получить знак различия с помощью побитовых операторов. Эти две точки описывают необходимость переменной int_diff как целочисленного типа.
    3. Теперь предположим, что мы находим различие в переменной 'diff', теперь есть 3 возможности для значений 'diff' независимо от знака этих значений. (А). | diff |> = 1, (б). 0 <| diff | <1, (c). | Дифф | == 0. </li>
    4. Когда мы присваиваем двойное значение целочисленной переменной, десятичная часть теряется.
    5. Для случая (а) значение 'int_diff'> 0 (то есть 1,2, ...). Для двух других случаев int_diff = 0.
    6. Условие (temp_diff-int_diff) || 0.0 проверяет, равно ли diff == 0, поэтому оба числа равны.
    7. Если diff! = 0, тогда мы проверяем, является ли int_diff | 0 истинным, т.е. case (b) истинен
    8. В цикле while мы пытаемся получить значение int_diff как ненулевое, так что значение int_diff также получает знак diff.
0 голосов
/ 25 августа 2014

Логика, описанная в задаче, может быть объяснена так: если 1-е число меньше, то 0 будет вычтено, иначе разница будет вычтена из 1-го числа, чтобы получить 2-е число.Я нашел еще одно математическое решение, которое, как мне кажется, немного проще для понимания этой концепции.

Рассматривая a и b как заданные числа

c=|a/b|+1;
d=(c-1)/b;
smallest number= a - d*(a-b);

Опять же, идея состоит в том, чтобы найти k, которое является вялым0 или 1 и умножьте его с разницей в два числа. И, наконец, это число должно быть вычтено из 1-го числа, чтобы получить меньшее из двух чисел.PS это решение потерпит неудачу, если 2-е число равно нулю

0 голосов
/ 01 августа 2014

Есть один путь

 public static int Min(int a, int b)
  {
   int dif = (int)(((uint)(a - b)) >> 31);
   return a * dif + b * (1 - dif);
  }

и один

return (a>=b)?b:a;
0 голосов
/ 25 июля 2013

static int mymax (int a, int b)

    {
        int[] arr;
        arr = new int[3];
        arr[0] = b;
        arr[1] = a;
        arr[2] = a;
        return arr[Math.Sign(a - b) + 1];

    }

Если b> a, тогда (ab) будет отрицательным, знак вернет -1, добавив 1, мы получим индекс 0, который равен b, если b = a, то ab будет 0, +1 даст 1 индекс, так что не имеет значения, возвращаем ли мы a или b, когда a> b, тогда ab будет положительным и знак вернет 1, добавив 1, мы получим индекс 2, где хранится a.

0 голосов
/ 23 октября 2012
int a=151;
int b=121;
int k=Math.abs(a-b);
int j= a+b;
double k1=(double)(k);
double j1= (double) (j);
double c=Math.ceil(k1/2) + Math.floor(j1/2);
int c1= (int) (c);
System.out.println(" Max value = " + c1);
0 голосов
/ 11 июля 2011

Думаю, мы можем просто умножить числа на их побитовые сравнения, например:

int max=(a>b)*a+(a<=b)*b;
...