Using only bitwise operators (|, &, ~, ^, >>, <<) and other basic operators like +, -, and !, is it possible to replace the "==" below?
int equal(int x, int y) {
return x == y;
}
Remember that an XOR is the exactly same as NOT EQUALS and XNOR is exactly the same as EQUALS. So, the following will give you exactly what you want:
return !(x ^ y);
Two numbers are equal if there is no difference between them:
int equal(int x, int y){
return !(x-y);
}
The C ! operator is really just shorthand for != 0, so using it seems very close to cheating :)
Here's my take just using bitwise operations, assuming a 32-bit two's complement machine with arithmetic right shifts (technically, in C arithmetic right shifts are undefined, but every C compiler I've ever seen on a two's complement machine supports this correctly):
int t = (x - y) | (y - x); // <0 iff x != y, 0 otherwise
t >>= 31; // -1 iff x != y, 0 otherwise
return 1 + t; // 0 iff x != y, 1 otherwise
That said, actual compilers don't have this problem. Real hardware actually has direct support for comparisons. The details depend on the architecture, but there's two basic models:
Condition codes returned for arithmetic operations (e.g. x86 and ARM do this). In this case, there's usually a "compare" instruction which subtracts two values, doesn't write back to an integer register but sets the condition code/flags based on the result.
More RISC-like platforms typically have direct "branch if equal" and "branch if less than" operands that do a comparison and branch based on the result. It's basically equivalent to the C code
if (a == b) goto label;
or
if (a < b) goto label;
all in one machine instruction.
This example is the same as subtraction, but is more explicit as to how some architectures do register comparison (like the ARM, I believe).
return !(1 + ~x + y);
The 1 signifies the carry-bit input into the ALU. One number x is bitwise complemented. Taking the complement and adding 1 produces the two's complement of the number (x becomes -x), and then it's added to the other number to get the difference to determine equality.
So if both numbers are equal, you get -x + x => 0.
(On a register level the ! operator isn't done, and you just test the "zero bit" of the condition codes or flags register, which gets set if the register operation produces a result of zero, and is clear otherwise.)
As XOR is same as (!=), hence (x ^ y) will return 0 only for equal values.
My take is the following because it is sensible, uses bit-wise operator and working.
int notEqual(int x, int y){
return (x ^ y);
}
My Take on this
int equal(int x, int y){
if((x & ~y) == 0)
return 1;
else
return 0;
}
Explanation: If x == y, then x & ~y evaluates to 0 return 1, else return 0 as x!=y.
Edit1: The above is equivalent to
int equal(int x, int y){
return !(x & ~y) ; // returns 1 if equal , 0 otherwise.
}
The above code fails in certain cases where the Most significant bit turns to 1. The solution is to add a 1. i.e correct answer is
return !(x & (~y +1) );
Related
I'm trying to create a function to determine whether x is less than or equal to y.
The legal operators are ! ~ & ^ | + << >>, and the function says "if x <= y then return 1, else return 0"
My thought process is to check whether x-y is negative, and then right shift 31 bits and compare with 1. No matter what adjustments I do, it returns 0, when it's expecting 1.
This is what I have so far:
int isLessOrEqual(int x, int y) {
return (((x - y) >> 31) & 1) | (!(x^y));
}
Can anyone please help me see what I'm doing wrong?
I also tried with all of these return statements:
return (!(x^y)) | (((x+(~y+1)) >> 31 ) & 1);
return ~(((x+(~y+1)) >> 31 ) & 1) | (!(x^y));
return !(((x+(~y+1)) >> 31 ) & 1) | (!(x^y));
return (((x+(~y+1)) >> 31 ) & 1);
return (((x+y+(~1)) >> 31 ) & 1) | (!(x^y));
return (((x+y+(~1) >> 31 ) & 1) | (!(x^y));
return (((x+(~y+1)) >> 31 ) & 0);
I am not going to do your assignment for you, but I will try to get you pointed in the right direction.
My thought process is to check whether x-y is negative, and then right shift 31 bits and compare with 1.
I take you to mean that you want to test whether x-y is negative by shifting the result and comparing with 1, and then to use that in determining the function's return value. That's more or less ok, but there is some room for concern about right shifting negative numbers, as the result is implementation defined. I do not think that's causing you trouble in practice, however.
No matter what adjustments I do, it returns 0, when it's expecting 1.
In some cases, yes. But there are many other cases where that approach, correctly implemented, produces the desired result. About 75% of cases, in fact. Specifically,
it works (only) when x-y does not overflow.
Additionally,
since you're not allowed to use the - operator, you'll need to perform the two's complement conversion and use + instead.
you can avoid the shifting by ANDing with INT_MIN instead of with 1. This yields a nonzero result (INT_MIN) when and only when the other operand of the & has its sign bit set. If you like, you can convert non-zero to exactly 1 by logically negating twice (!!x).
You can slightly simplify the overall computation by using y-x instead of x-y. Then you don't need special accommodation for the x == y case.
You know (or can know) that neither x - y nor y - x overflows when x and y have the same sign.* In that case, you can use one or another variation on testing the arithmetic difference of the arguments. On the other hand, there is a simpler alternative when the two have differing signs (left as an exercise).
To combine those into a single expression, you can compute bitmasks that effect a selection between two alternatives. Schematically:
return (WHEN_SIGNS_MATCH_MASK(x, y) & IS_DIFFERENCE_NON_NEGATIVE(y, x))
| (WHEN_SIGNS_DIFFER_MASK(x, y) & ...);
The WHEN_SIGNS_MATCH_MASK should evaluate to 0 when the signs differ and to -1 (== all bits 1) or another appropriate value when the signs are the same. The WHEN_SIGNS_DIFFER_MASK implements the opposite sense of that sign comparison. The IS_DIFFERENCE_NON_NEGATIVE expands to your subtraction-based computation, and the ... is the alternative approach for the differing-sign case. (I've implied using macros. You don't need to use macros, but doing so will probably make your code clearer.)
*A sufficient condition, but not a necessary one.
For entertainment, suppose we want to compare two numbers of format double using the c language, and we can only use mathematical equations that use the arithmetic operators +, -, *, /, %, and fabs() and pow() to check equal to (==), less than (<), and greater than (>). Similar to the real relational operators ==, <, and >, the code we write must return True (1) or False (0) for each of the different kinds of checks.
For example, without using any other operators than +, -, *, /, %, and fabs() and pow(), if we determine that two variables a and b are equal, we should return True or 1, otherwise, return False or 0. It is better to return integers 0 and 1 instead of boolean True and False. To complicate things, we cannot use the real relational operators, logical operators, bitwise operators, or any other operators. Further, we cannot use switch statements or conditional statements. How to do so?
I know how to find the smaller value of x and y, that is to say x < y can be calculated as ((x + y) + fabs(x-y))/2. Further, to find x > y, it is ((x + y) - fabs(x-y))/2. However, those equations return the value x or y depending on the comparisons equation, and I need them to return 0 or 1. Similarly, I need some code equation that returns a 0 or 1 if x and y are equal (==) to each other, and must do so using only +, -, *, /, %, and fabs() and pow().
Any of given operators +, -, *, / , applied to double operands will result in double, as well as fabs() and pow() function. So there is no way to convert double to integer, using only provided operators and fabs() and pow() function.
Also, % operator is for integers only. There is a fmod() function, that provides the same functionality for floating-point numbers.
We can achieve that the result of our calculations, using only provided operators and functions will be represented in memory in the same way, as integer 0 and 1.
For example, these functions made for float i.e. 32bit floating point numbers:
float largerOf(float x, float y){
return ((x + y) + fabs(x-y)) / 2.0;
}
float smallerOf(float x, float y){
return ((x + y) - fabs(x-y)) / 2.0;
}
int isEqual(float x, float y){
float tmp = smallerOf(x, y) / largerOf(x, y);
tmp /= 3.4028235E38;
tmp /= 4194303.9999999997;
return *((int*)(&tmp));
}
int lessThan(float x, float y){
float tmp = smallerOf(x, y) / x;
tmp /= 3.4028235E38;
tmp /= 4194303.9999999997;
return (*((int*)(&tmp)))-isEqual(x,y);
}
int greaterThan(float x, float y){
float tmp = smallerOf(x, y) / y;
tmp /= 3.4028235E38;
tmp /= 4194303.9999999997;
return (*((int*)(&tmp)))-isEqual(x,y);
}
This solution uses the fact, that smaller of two values, divided by larger of two values will result in a value less than or equal to 1.0. Then, resulting in value after division is divided again by two hardcoded constants in an attempt to get the floating-point number with the rightmost bit set if and only if result of first division was exactly 1.0. After all, we accessing the memory, containing the floating-point number, as if it was containing integer result.
Please note, that this solution is poorly tested and may probably misbehave in many different ways. For example, values 2.0 and 1.9999993 behaves well, but 2.0 and 1.9999994 is considered equal despite the fact that 32bit floating point number can represent values 1.9999993 and 1.9999994 and they are both distinguishable from 2.0.
I am learning bit algorithm and saw the equation that finds the max of two values:
r = x ^ ((x ^ y) & -(x < y)); // max(x, y)
The explanation says this equation will find the max without using comparison and "if x < y, then -(x < y) will be all ones". I cannot comprehend what the explanation means because I see a "less than" operator in the equation and if that is an less than operator, (x < y) should return only one bit of data. Therefore, for the explanation to make sense, the sign "<" cannot be the less than operator. I looked at the list of C operators and did not find other meanings for operator "<". Can someone tell me what does the operator "<" do in this equation? Thanks!
This is a very tricky code. The truth is that C does not have any Boolean type: it uses integer instead: 0 for false and 1 for true.
Therefore -(x<y) means
0 if x≥y
-1 if x<y
It is then used as a bit mask.
Edit
As suggested by Jonathan Leffler in comments, C has now a _Bool.
I made this small program to check what is it and how it is used:
#include <stdio.h>
int main() {
_Bool bFalse = 1>2;
printf("size of _Bool: %lu\nsize of comparison result: %lu\n", sizeof(bFalse), sizeof(1>2));
return 0;
}
This outputs:
size of _Bool: 1
size of comparison result: 4
In other words _Bool is one byte (a char), but it is not used as a result of Boolean comparisons (my compiler generates 4 bytes, that is, an int)
Note: tested with Clang on an Intel processor.
Edit: fix the types as kindly suggested in comments (and after checking the clang IR)
"if x < y, then -(x < y) will be all ones"
This is because, if x is less than y, condition evaluates to true (equal to 1). Notice the negetive sign before comparison, it makes the "1" of comparison result as "-1". In binary world, -1 has an all 1 representation, see Two's_complement. Example: 1111 1111 = -1.
However, if x > y, you get a -0 which is again all zero in binary.
Here, '<' is only a "x is_less_than y" comparison check, a logical operator.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How can I multiply and divide using only bit shifting and adding?
I have to write functions to perform binary subtraction, multiplication, and division without using any arithmetic operators except for loop control. I've only written code in Java before now, so I'm having a hard time wrapping my head around this.
Starting with subtraction, I need to write a function with prototype
int bsub(int x, int y)
I know I need to convert y to two's complement in order to make it negative and add it to x, but I only know how to do this by using one's complement ~ operator and adding 1, but I can't use the + operator.
The badd function was provided, and I will be able to implement it in bsub if I can figure out how to make y a negative number. The code for badd is shown below. Thanks in advance for any tips.
int badd(int x,int y){
int i;
char sum;
char car_in=0;
char car_out;
char a,b;
unsigned int mask=0x00000001;
int result=0;
for(i=0;i<32;i++){
a=(x&mask)!=0;
b=(y&mask)!=0;
car_out=car_in & (a|b) |a&b;
sum=a^b^car_in;
if(sum) {
result|=mask;
}
if(i!=31) {
car_in=car_out;
} else {
if(car_in!=car_out) {
printf("Overflow occurred\n");
}
}
mask<<=1;
}
return result;
}
Well, subtracting in bitwise operations without the + or - operators is slightly tricky, but can be done. You have the basic idea with the complement, but without using + it becomes slightly tricky.
You can do it by first setting up addition with bit-wise only, then using that, you can do subtraction. Which is used for the complement, So the code looks like this:
int badd(int n1, int n2){
int carry, sum;
carry = (n1 & n2) << 1; // Find bits that are used for carry
sum = n1 ^ n2; // Add each bit, discard carry.
if (sum & carry) // If bits match, add current sum and carry.
return badd(sum, carry);
else
return sum ^ carry; // Return the sum.
}
int bsub(int n1, int n2){
// Add two's complement and return.
return badd(n1, badd(~n2, 1));
}
And then if we use the above code in an example:
int main(){
printf("%d\n", bsub(53, 17));
return 0;
}
Which ends up returning 36. And that is how subtraction works with bitwise only operations.
Afterwards multiplication and division get more complicated, but can be done; for those two operations, use shifts along with addition and/or subtraction to get the job done. You may also want to read this question and this article on how to do it.
You have to implement the binary addition first:
Example with 4 bits:
a = 1101
b = 1011
mask will range from 0001 to 1000
for (i=0;i<4;i++) {
x = a & pow(2, i); //mask, you can shift left as well
y = b & pow(2, i);
z = x ^ y; //XOR to calculate addition
z = z ^ carry; //add previous carry
carry = x & y | x ^ carry | y ^ carry; //new carry
}
This is pseudocode. The mask allows for operating bit by bit from left to right. You'll have to store z conveniently into another variable.
Once you have the addition, you'll be able to implement subtraction by 1'complementing and adding 1.
Multiplication goes the same way, but slightly more difficult. Basically it's the same division method you learned at school, using masks to select bits conveniently and adding the intermediate results using the addition above.
Division is a bit more complicated, it would take some more time to explain but basically it's the same principle.
using only bitwise operators (|, &, ~, ^, >>, <<), is it possible to replace the != below?
// ...
if(a != b){
// Some code
}
/// ...
this is mainly out of self interest, since I saw how to do it with == but not !=.
if(a ^ b) {
//some code
}
should work.
You can also use your preferred method for == and add ^ 0xFFFFFFFF behind it (with the right amount of Fs to match the length of the datatype). This negates the value (same as ! in front of it).
a != b means that there is at least one different bit in the bit representations of a and b. The XOR bit operator returns 1 if both input bit operands are different, 0 otherwise.
So, you can apply a XOR operation to a and b and check if the result is not equal to zero.
A bitwise version of the '!=' test could look something like:
if((a - b) | (b - a)) {
/* code... */
}
which ORs the two subtractions. If the two numbers are the same, the result will be 0. However, if they differ (aka, the '!=' operator) then the result will be 1.
Note: The above snippet will only work with integers (and those integers should probably be unsigned).
If you want to simulate the '==' operator, however, check out Fabian Giesen's answer in Replacing "==" with bitwise operators
x ^ y isn't always sufficient. Use !!(x ^ y). Values expecting a one bit return value will not work with x ^ y since it leaves a remainder that could be greater than just 1.
Yes, using this:
if (a ^ b) { }
"~" is equaled to NOT so that should work. example would be "a & ~b".