Код, который я предоставляю, предназначен для поиска максимума между двумя числами, числа могут быть любого типа данных (целые, плавающие). Если введенные числа равны, то функция возвращает число.
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), мы умножаем результат на разницу двух чисел, логика дано следующим образом:
- если a> b, то a-b> 0, т. Е. Равно + ve, поэтому результат равен 0 (т. Е. R = 0). Таким образом, a- (a-b) * r => a- (a-b) * 0, что дает «a» как максимум.
- если a a- (a-b) * 1 => a-a + b => b, что дает «b» как максимум.
Теперь есть две оставшиеся точки: 1. использование цикла while и 2. почему я использовал переменную int_diff в качестве целого числа. Чтобы ответить на них правильно, мы должны понимать некоторые моменты:
- Значения плавающего типа не могут использоваться в качестве операнда для побитовых операторов.
- По вышеуказанной причине нам нужно получить значение в целочисленном значении, чтобы получить знак различия с помощью побитовых операторов. Эти две точки описывают необходимость переменной int_diff как целочисленного типа.
- Теперь предположим, что мы находим различие в переменной 'diff', теперь есть 3 возможности для значений 'diff' независимо от знака этих значений. (А). | diff |> = 1, (б). 0 <| diff | <1, (c). | Дифф | == 0. </li>
- Когда мы присваиваем двойное значение целочисленной переменной, десятичная часть теряется.
- Для случая (а) значение 'int_diff'> 0 (то есть 1,2, ...). Для двух других случаев int_diff = 0.
- Условие (temp_diff-int_diff) || 0.0 проверяет, равно ли diff == 0, поэтому оба числа равны.
- Если diff! = 0, тогда мы проверяем, является ли int_diff | 0 истинным, т.е. case (b) истинен
- В цикле while мы пытаемся получить значение int_diff как ненулевое, так что значение int_diff также получает знак diff.