Write a C program to find the smallest of 2 integers with & without using any of the comparison operators.Also use this to calculate maximum of 3 integers.
On some rare machines where branching is expensive, the below obvious approach to find minimum can be slow as it uses branching.
/* The obvious approach to find minimum (involves branching) */
int min(int x, int y)
{
return (x < y) ? x : y
}
Below are the methods to get minimum(or maximum) without using branching. Typically, the obvious approach is best, though.
Method 1(Use XOR and comparison operator)
Minimum of x and y will be
y ^ ((x ^ y) & -(x < y))
It works because if x < y, then -(x < y) will be all ones, so r = y ^ (x ^ y) & ~0 = y ^ x ^ y = x. Otherwise, if x >= y, then -(x < y) will be all zeros, so r = y ^ ((x ^ y) & 0) = y. On some machines, evaluating (x < y) as 0 or 1 requires a branch instruction, so there may be no advantage.
To find the maximum, use
x ^ ((x ^ y) & -(x < y));
#include<stdio.h>
int min(int x, int y)
{
return y ^ ((x ^ y) & -(x < y));
}
int max(int x, int y)
{
return x ^ ((x ^ y) & -(x < y));
}
int main()
{
int x = 15;
int y = 6;
printf("Minimum of %d and %d is ", x, y);
printf("%d", min(x, y));
printf("\nMaximum of %d and %d is ", x, y);
printf("%d", max(x, y));
getchar();
}
Method 2(Use subtraction and shift)
If we know that
INT_MIN <= (x - y) <= INT_MAX
, then we can use the following, which are faster because (x - y) only needs to be evaluated once.
Minimum of x and y will be
y + ((x - y) & ((x - y) >>(sizeof(int) * CHAR_BIT - 1)))
This method shifts the subtraction of x and y by 31 (if size of integer is 32). If (x-y) is smaller than 0, then (x -y)>>31 will be 1. If (x-y) is greater than or equal to 0, then (x -y)>>31 will be 0.
So if x >= y, we get minimum as y + (x-y)&0 which is y.
If x < y, we get minimum as y + (x-y)&1 which is x.
Similarly, to find the maximum use
x - ((x - y) & ((x - y) >> (sizeof(int) * CHAR_BIT - 1)))
#include<stdio.h>
#define CHAR_BIT 8
/*Function to find minimum of x and y*/
int min(int x, int y)
{
return y + ((x - y) & ((x - y) >>
(sizeof(int) * CHAR_BIT - 1)));
}
/*Function to find maximum of x and y*/
int max(int x, int y)
{
return x - ((x - y) & ((x - y) >>
(sizeof(int) * CHAR_BIT - 1)));
}
int main()
{
int x = 15;
int y = 6;
printf("Minimum of %d and %d is ", x, y);
printf("%d", min(x, y));
printf("\nMaximum of %d and %d is ", x, y);
printf("%d", max(x, y));
getchar();
}
Note that the 1989 ANSI C specification doesn't specify the result of signed right-shift, so above method is not portable. If exceptions are thrown on overflows, then the values of x and y should be unsigned or cast to unsigned for the subtractions to avoid unnecessarily throwing an exception, however the right-shift needs a signed operand to produce all one bits when negative, so cast to signed there.
Let 3 input numbers be x, y and z.
Method 1 (Repeated Subtraction)
Take a counter variable c and initialize it with 0. In a loop, repeatedly subtract x, y and z by 1 and increment c. The number which becomes 0 first is the smallest. After the loop terminates, c will hold the minimum of 3.
#include<stdio.h>
int smallest(int x, int y, int z)
{
int c = 0;
while ( x && y && z )
{
x--; y--; z--; c++;
}
return c;
}
int main()
{
int x = 12, y = 15, z = 5;
printf("Minimum of 3 numbers is %d", smallest(x, y, z));
return 0;
}
This methid doesn’t work for negative numbers. Method 2 works for negative nnumbers also.
Method 2 (Use Bit Operations)
Once we have functionality to find minimum of 2 numbers, we can use this to find minimum of 3 numbers.
#include<stdio.h>
#define CHAR_BIT 8
int min(int x, int y)
{
return y + ((x - y) & ((x - y) >>
(sizeof(int) * CHAR_BIT - 1)));
}
int smallest(int x, int y, int z)
{
return min(x, min(y, z));
}
int main()
{
int x = 12, y = 15, z = 5;
printf("Minimum of 3 numbers is %d", smallest(x, y, z));
return 0;
}
On some rare machines where branching is expensive, the below obvious approach to find minimum can be slow as it uses branching.
/* The obvious approach to find minimum (involves branching) */
int min(int x, int y)
{
return (x < y) ? x : y
}
Below are the methods to get minimum(or maximum) without using branching. Typically, the obvious approach is best, though.
Method 1(Use XOR and comparison operator)
Minimum of x and y will be
y ^ ((x ^ y) & -(x < y))
It works because if x < y, then -(x < y) will be all ones, so r = y ^ (x ^ y) & ~0 = y ^ x ^ y = x. Otherwise, if x >= y, then -(x < y) will be all zeros, so r = y ^ ((x ^ y) & 0) = y. On some machines, evaluating (x < y) as 0 or 1 requires a branch instruction, so there may be no advantage.
To find the maximum, use
x ^ ((x ^ y) & -(x < y));
#include<stdio.h>
int min(int x, int y)
{
return y ^ ((x ^ y) & -(x < y));
}
int max(int x, int y)
{
return x ^ ((x ^ y) & -(x < y));
}
int main()
{
int x = 15;
int y = 6;
printf("Minimum of %d and %d is ", x, y);
printf("%d", min(x, y));
printf("\nMaximum of %d and %d is ", x, y);
printf("%d", max(x, y));
getchar();
}
Method 2(Use subtraction and shift)
If we know that
INT_MIN <= (x - y) <= INT_MAX
, then we can use the following, which are faster because (x - y) only needs to be evaluated once.
Minimum of x and y will be
y + ((x - y) & ((x - y) >>(sizeof(int) * CHAR_BIT - 1)))
This method shifts the subtraction of x and y by 31 (if size of integer is 32). If (x-y) is smaller than 0, then (x -y)>>31 will be 1. If (x-y) is greater than or equal to 0, then (x -y)>>31 will be 0.
So if x >= y, we get minimum as y + (x-y)&0 which is y.
If x < y, we get minimum as y + (x-y)&1 which is x.
Similarly, to find the maximum use
x - ((x - y) & ((x - y) >> (sizeof(int) * CHAR_BIT - 1)))
#include<stdio.h>
#define CHAR_BIT 8
/*Function to find minimum of x and y*/
int min(int x, int y)
{
return y + ((x - y) & ((x - y) >>
(sizeof(int) * CHAR_BIT - 1)));
}
/*Function to find maximum of x and y*/
int max(int x, int y)
{
return x - ((x - y) & ((x - y) >>
(sizeof(int) * CHAR_BIT - 1)));
}
int main()
{
int x = 15;
int y = 6;
printf("Minimum of %d and %d is ", x, y);
printf("%d", min(x, y));
printf("\nMaximum of %d and %d is ", x, y);
printf("%d", max(x, y));
getchar();
}
Note that the 1989 ANSI C specification doesn't specify the result of signed right-shift, so above method is not portable. If exceptions are thrown on overflows, then the values of x and y should be unsigned or cast to unsigned for the subtractions to avoid unnecessarily throwing an exception, however the right-shift needs a signed operand to produce all one bits when negative, so cast to signed there.
Maximum of 3 integers:
Let 3 input numbers be x, y and z.
Method 1 (Repeated Subtraction)
Take a counter variable c and initialize it with 0. In a loop, repeatedly subtract x, y and z by 1 and increment c. The number which becomes 0 first is the smallest. After the loop terminates, c will hold the minimum of 3.
#include<stdio.h>
int smallest(int x, int y, int z)
{
int c = 0;
while ( x && y && z )
{
x--; y--; z--; c++;
}
return c;
}
int main()
{
int x = 12, y = 15, z = 5;
printf("Minimum of 3 numbers is %d", smallest(x, y, z));
return 0;
}
This methid doesn’t work for negative numbers. Method 2 works for negative nnumbers also.
Method 2 (Use Bit Operations)
Once we have functionality to find minimum of 2 numbers, we can use this to find minimum of 3 numbers.
#include<stdio.h>
#define CHAR_BIT 8
int min(int x, int y)
{
return y + ((x - y) & ((x - y) >>
(sizeof(int) * CHAR_BIT - 1)));
}
int smallest(int x, int y, int z)
{
return min(x, min(y, z));
}
int main()
{
int x = 12, y = 15, z = 5;
printf("Minimum of 3 numbers is %d", smallest(x, y, z));
return 0;
}
//USING BIT Manipulation
ReplyDeleteint min_of_2_bit(int x, int y)
{
return y + ((x - y) & ((x - y) >>
(sizeof(int) * CHAR_BIT - 1)));
}
int max_of_2_bit(int x, int y)
{
return x - ((x - y) & ((x - y) >>
(sizeof(int) * CHAR_BIT - 1)));
}