Using only:
<< >> | ^ & +
How can I make a function that is equivalent to the logical not operator (!)?
Right now I have:
int i = (~x + 1) >> 31;
int j = (x + 1) >> 31;
i = i | j;
i = i & 1;
return i ^ 1;
It works for everything, but -1.
I will assume that you are working with ints that are 32-bit, signed, and use 2's complement notation. The unique thing about the number 0 is that neither 0 nor its negation have a 1 for the sign bits. This code would work if you were allowed to use the negation operator (-):
int not(int x)
{
return (-x | x) >> 31 & 1 ^ 1;
}
You can't use minus, but that is ok because for all x we know that -x is equal to ~x + 1 which is equal to (x ^ -1) + 1. That's how 2's complement notation works. So the final answer is:
int not(int x)
{
return ( (x^-1)+1 | x ) >> 31 & 1 ^ 1;
}
EDIT 1:
Ok, here is the "ANSI" version of the function that makes no assumption about the size of the int and does not rely on the undefined behavior of right-shifting a signed int. It works for me in MinGW:
int not(int x)
{
unsigned int y = x;
return (( ((y^-1)+1) | y ) >> (sizeof(x)*8-1)) ^ 1;
}
Assuming that x is a 32-bit unsigned value:
x = x | (x >> 1)
x = x | (x >> 2)
x = x | (x >> 4)
x = x | (x >> 8)
x = x | (x >> 16)
At this point, if x was 0 then it's still 0. If it had a non-zero value, it now has the bit pattern 111....111.
With a two-complement representation, you can now simply add 1 and get the desired result:
x = x + 1
This solution assumes quite a bit about integer representation, types, etc.
(The "code" above is not valid C code, of course).
Kind of 'cheating', but:
bool logicalNot(int i)
{
return((bool)i ^ true);
}
I'm assuming there's nothing in the rules about composition of functions/typecasting/implicit type conversions?
Related
I'm currently working through the K&R C book exercises and am on exercise 8 of chapter 2. The challenge is to write a function 'rotright' that rotates (or circle shifts) the bits of unsigned integer x by n bits. I believe I've come up with a solution, but it's not returning what I would expect. Given the number 213, which is 11010101 in binary, rotating 2 bits to the right would yield 01110101, which is 117. However, my program upon being given x=213 and n=2 returns 53. I've tried writing out the process of what's happening to the integer in binary form in comments and can't find a problem. Any help would be appreciated.
#include <stdio.h>
unsigned rotright(unsigned x, int n)
{
/* Example with x = 11010101 (213 in decimal), n = 2
First iteration:
x = (01101010) | ~(11111111 >> 1) = 11101010
Second iteration:
x = (01110101) | ~(11111111 >> 0) = 01110101
Returns 01110101
right shifts only if last bit of x == 1, then sets first bit of right shifted x to 1
if last bit of x == 0, x is right shifted by 1 and then unchanged.
(01101010) | ~(11111111 >> (11010101 & 00000001))
= 01101010 | ~(11111111 >> 00000001)
= 01101010 | 10000000 = 11101010
(11101010) | ~(11111111 >> (11101010 & 00000001))
= 01110101 | ~(11111111 >> 0)
= 01110101 | 00000000 = 01110101
*/
for (; n > 0; n--)
x = (x >> 1) | ~(~0 >> (x & 1));
return x;
}
int main()
{
printf("%d\n", rotright(213, 2));
return 0;
}
x = (x >> 1) | ~(~0 >> (x & 1));
you get 53 because this is (213 >> 2)
~(~0 >> (x & 1)) is always 0, because ~0 is -1, and (-1 >> n) is again -1 in your case, and finally ~(-1) is 0
You want that :
#include <stdio.h>
#include <limits.h>
unsigned rotright(unsigned x, int n)
{
unsigned mask = (1u << (CHAR_BIT * sizeof(int) - 1));
for (; n > 0; n--) {
x = (x / 2) | ((x & 1) ? mask : 0);
}
return x;
}
int main()
{
printf("%d\n", rotright(213, 2));
return 0;
}
On 32bits the result is 1073741877 being 1000000000000000000000000110101, not 117 whose supposes you work on 8 bits
unsigned long ccNextPOT(unsigned long x){
x = x - 1;
x = x | (x >> 1);
x = x | (x >> 2);
x = x | (x >> 4);
x = x | (x >> 8);
x = x | (x >>16);
return x + 1;
}
The OR and SHIFT statements fills with ones all bits of x to the right of most significant bit (up to 32 bits). Together with the pre-decrement and post-increment statements, this computes (as the function name suggets) the next power-of-two number, equal or greater than the given number (if x is greater than 0 and less than 2^32)
For this assignment I can only use basic bitwise operators and no control structures, so I've come up with this code so far to convert sign-magnitude to two's complement.
int sm2tc(int x) {
// Invert and add 1
// Problem: sm has 2 zeros.. 1000...000 & 0000...000
int tmin = 1 << 31;
int mask = x >> 31; // Determine sign of x
int mask2 = ~tmin; // Negate tmin to get 0111111...
int first = (x ^ mask) + (~mask + 1) ;
int second = first & mask2; // Turns of MSB
return second;
}
Where have I gone wrong?
So, what you really want to compute is
result = (x & sign_bit) ? -(x & ~sign_bit) : x;
But of course you're not allowed control structures. The first step is to rewrite -(x & ~sign_bit) using just the + and ^ operators: (-1 ^ (x & ~sign_bit)) - -1. Now note that if (x & sign_bit) is zero then (0 ^ (x & ~sign_bit)) - 0 is equal to x. We now have
result = (x & sign_bit) ? (-1 ^ (x & ~sign_bit)) - -1 : (0 ^ (x & ~sign_bit)) - 0
You then just need to replace the -1 and 0 with functions of x that generate those values depending on the sign bit, and lo and behold both sides of the condition become the same expression and the condition becomes unnecessary.
Check whether a number x is nonzero using the legal operators except !.
Examples: isNonZero(3) = 1, isNonZero(0) = 0
Legal ops: ~ & ^ | + << >>
Note : Only bitwise operators should be used. if, else, for, etc. cannot be used.
Edit1 : No. of operators should not exceed 10.
Edit2 : Consider size of int to be 4 bytes.
int isNonZero(int x) {
return ???;
}
Using ! this would be trivial , but how do we do it without using ! ?
The logarithmic version of the adamk function:
int isNotZero(unsigned int n){
n |= n >> 16;
n |= n >> 8;
n |= n >> 4;
n |= n >> 2;
n |= n >> 1;
return n & 1;
};
And the fastest one, but in assembly:
xor eax, eax
sub eax, n // carry would be set if the number was not 0
xor eax, eax
adc eax, 0 // eax was 0, and if we had carry, it will became 1
Something similar to assembly version can be written in C, you just have to play with the sign bit and with some differences.
EDIT: here is the fastest version I can think of in C:
1) for negative numbers: if the sign bit is set, the number is not 0.
2) for positive: 0 - n will be negaive, and can be checked as in case 1. I don't see the - in the list of the legal operations, so we'll use ~n + 1 instead.
What we get:
int isNotZero(unsigned int n){ // unsigned is safer for bit operations
return ((n | (~n + 1)) >> 31) & 1;
}
int isNonZero(unsigned x) {
return ~( ~x & ( x + ~0 ) ) >> 31;
}
Assuming int is 32 bits (/* EDIT: this part no longer applies as I changed the parameter type to unsigned */ and that signed shifts behave exactly like unsigned ones).
Why make things complicated ?
int isNonZero(int x) {
return x;
}
It works because the C convention is that every non zero value means true, as isNonZero return an int that's legal.
Some people argued, the isNonZero() function should return 1 for input 3 as showed in the example.
If you are using C++ it's still as easy as before:
int isNonZero(int x) {
return (bool)x;
}
Now the function return 1 if you provide 3.
OK, it does not work with C that miss a proper boolean type.
Now, if you suppose ints are 32 bits and + is allowed:
int isNonZero(int x) {
return ((x|(x+0x7FFFFFFF))>>31)&1;
}
On some architectures you may even avoid the final &1, just by casting x to unsigned (which has a null runtime cost), but that is Undefined Behavior, hence implementation dependant (depends if the target architecture uses signed or logical shift right).
int isNonZero(int x) {
return ((unsigned)(x|(x+0x7FFFFFFF)))>>31;
}
int is_32bit_zero( int x ) {
return 1 ^ (unsigned) ( x + ~0 & ~x ) >> 31;
}
Subtract 1. (~0 generates minus one on a two's complement machine. This is an assumption.)
Select only flipped bit that flipped to one.
Most significant bit only flips as a result of subtracting one if x is zero.
Move most-significant bit to least-significant bit.
I count six operators. I could use 0xFFFFFFFF for five. The cast to unsigned doesn't count on a two's complement machine ;v) .
http://ideone.com/Omobw
Bitwise OR all bits in the number:
int isByteNonZero(int x) {
return ((x >> 7) & 1) |
((x >> 6) & 1) |
((x >> 5) & 1) |
((x >> 4) & 1) |
((x >> 3) & 1) |
((x >> 2) & 1) |
((x >> 1) & 1) |
((x >> 0) & 1);
}
int isNonZero(int x) {
return isByteNonZero( x >> 24 & 0xff ) |
isByteNonZero( x >> 16 & 0xff ) |
isByteNonZero( x >> 8 & 0xff ) |
isByteNonZero( x & 0xff );
}
basically you need to or the bits. For instance, if you know your number is 8 bits wide:
int isNonZero(uint8_t x)
{
int res = 0;
res |= (x >> 0) & 1;
res |= (x >> 1) & 1;
res |= (x >> 2) & 1;
res |= (x >> 3) & 1;
res |= (x >> 4) & 1;
res |= (x >> 5) & 1;
res |= (x >> 6) & 1;
res |= (x >> 7) & 1;
return res;
}
My solution is the following,
int isNonZero(int n)
{
return ~(n == 0) + 2;
}
My solution in C. No comparison operator. Doesn't work with 0x80000000.
#include <stdio.h>
int is_non_zero(int n) {
n &= 0x7FFFFFFF;
n *= 1;
return n;
}
int main(void) {
printf("%d\n", is_non_zero(0));
printf("%d\n", is_non_zero(1));
printf("%d\n", is_non_zero(-1));
return 0;
}
My solution,though not quite related to your question
int isSign(int x)
{
//return 1 if positive,0 if zero,-1 if negative
return (x > 0) - ((x & 0x80000000)==0x80000000)
}
if(x)
printf("non zero")
else
printf("zero")
The following function example should work for you.
bool isNonZero(int x)
{
return (x | 0);
}
This function will return x if it is non-zero, otherwise it will return 0.
int isNonZero(int x)
{
return (x);
}
int isNonZero(int x)
{
if ( x & 0xffffffff)
return 1;
else
return 0;
}
Let assume Int is 4 byte.
It will return 1 if value is non zero
if value is zero then it will return 0.
return ((val & 0xFFFFFFFF) == 0 ? 0:1);
isPositive - return true if x > 0, otherwise false
Example: isPositive(-1)
Legal ops: ! ~ & ^ | + << >>
Max ops: 8
Note: No conditional statements are allowed.
inline bool isPositive(int32_t x) {
return ???;
}
int isPositive(int x) {
return !((x&(1<<31)) | !x);
}
x&(1<<31 is to check if the number is negative.
!x is to check if the number is zero.
A number is positive if it's not negative and not zero.
return !((x & 0x80000000) >> 31 | !x);
int isPositive(int x)
{
return (!(x & 0x80000000) & !!x);
}
Let's play with the sign bit: sign(~n) : 1 if n >= 0
To get rid of the case when n is 0: sign(~n + 1) : 1 if n > 0 or n = MIN_INT
So, we want the case when both functions return 1:
return ((~n & (~n + 1)) >> 31) & 1;
Why not use XOR (^)?
Try this,
{
return ((x>>31)&1)^(!!x);
}
It can deal with the 0 case well.
Assuming a two’s complement representation (not always the case!), this can be achieved by testing whether the most significant bit is set (in which case the number is negative).
Notice that the following code uses illegal operations (+, * and -) but these are for clarity and platform independence only. If you know more about your particular platform, e.g. that int is a 32 bit number, the relevant constants can be replaced by their numeric value.
// Will be 1 iff x < 0.
int is_neg = (x & (INT_MAX + 1)) >> (CHAR_BIT * sizeof(int) - 1);
// Will be 1 iff x != 0.
int is_not_zero = !!x;
return !is_neg & is_not_zero;
Haven't done assembler for quite a while, but as far as I remember first digit in the word represents negative value e.g. 1000 is -8, hence if most significant bit is 1 the number is negative. So the answer is !(x>>31)
if your working with a number system that uses the MSB as the signage bit, you can do:
int IsPositive(int x)
{
return (((x >> 31) & 1) ^ 1) ^ !x;
}
You have another option here:
int is_positive = (0&x^((0^x)&-(0<x)));
It is just a (0 & min(0,x)).
Test here
int isPositive(int x)
{
return ( ! (x & ( 1 << 31 ) ) );
}
It will return 1 if given no is +ve and return 0 if given no is -ve
in this function we got sign bit if that is 1 it means no is -ve so we return 0
and if sign bit is 0 it means number is +ve so we return 1 .
int x,len;
x = 0x0fffffff;
len = (sizeof(x) * 8) - 2;
if ((x>>len))
printf("Negative\n");
else
printf("Positive\n");
X will be either int or char(Integral type).
return !((x >> 31) & 1);
This is to check MSB.