Addition of two binary numbers using only logical operators AND, OR - c

I am new to programming and I want to add up two binary numbers (e.g. '10' and '01') in C but I am not allowed to use:
arithmetic operations +,-,*,/
bitwise operators (<<,^...)
iterations
arrays
So I have to rely on if/else-conditions and the two logical operators &&, ||. I know how to build an XOR, but how can I reach the "higher" digit (digit '1' in '10') when I am not allowed to use division at all?
I have read about the library function div(), but wouldn't it technically violate the rules?

This could be implemented as binary addition when it is performed by hand, but it is a tedious and will be more difficult if negative numbers are included.
For example, when adding:
+1
eca 0001
fdb 0011
----
0100
something along these lines could be implemented (very simplified and incomplete logic)
if (a == 1 && b == 1)
{
transferBit = 1;
res_0 = 0;
}
if (c == 0 && d == 1 && transferBit == 1)
{
res_1 = 0;
}
if (e == 0 && f == 0 && transferBit == 1)
{
transferBit = 0;
res_2 = 1;
}
etc.

Related

Solving a problem using logical operators in C programming language

#include <stdio.h>
void main()
{
int a = 11, b = 5;
if(a == 7 || 10){
printf("True");
}
else
printf("False");
}
This is my problem, i saw it in a question and was asked what the output would be.
i put false but the answer was true, im trying to understand why because a is not equal to any of them and the condition for it to be true is that a be equal to at least one of them
The expression in the if statement
if(a == 7 || 10){
is equivalent to
if( ( a == 7 ) || ( 10 ) ){
As 10 is not equal to 0 then the second operand of the logical OR operator || always evaluates to the logical true. So the whole expression used in the if statement has a result of the logical true.
In fact as a is not equal to 7 (due to its initialization) then the above if statement is equivalent to
if( 10 ){
This:
if (a == 7 || 10)
Does not test if a is equal to either 7 or 10.
The == operator will evaluate to 1 if both operands are equal, and 0 otherwise. The || operator will evaluate to 1 if at least one operand is non-zero, and 0 otherwise.
Also, the equality operator has higher precedence than the logical OR operator. So the above parses as:
if ((a == 7) || 10)
So the expression will be true if either a==7 evaluates to non-zero or 10 evaluates to non-zero. The latter is true so the condition is true.
It is a logical error. The way you type it you don't check whether a == 7 OR a == 10 (as you wish), rather you check only if a == 7 and second condition if (10) is always true.
The fix is pretty simple actually:
void main()
{
int a = 11, b = 5;
if(a == (7 || 10)){
printf("True");
}
else
printf("False");
}

precedence and execution of the operators in the statement

can't understand how the boolean variable "check" is assigned 1 or 0. here 2 == 2 is true but the 2 is not equal to 3 so it should be false.....
/* practicing the precedence of assignment operator */
#include <stdio.h>
int main() {
_Bool check;
check = (2 == 2 != 3);
printf("the value of _Bool is %d\n",check);
return 0;
}
i expect the result to be false
What actually happens is like this
(2 == 2 != 3)
becomes
(2 == 2) != 3)
which is
(1 != 3)
which in turn becomes
(1)
Perhaps what you needed was
(2 == 2 && 2 != 3)
Operator precedence is the same for == and !=, since they both belong to the same group equality operators. To separate operators with same precedence, we use operator associativity of that group, in this case left-to-right. Meaning that 2 == 2 != 3 is guaranteed to be parsed as (2 == 2) != 3. So we get:
2 == 2 -> 1
1 != 3 -> 1
Notably both == and != have higher precedence than =, so the parenthesis in your expression = (2 == 2 != 3) isn't needed (but good practice to use if you are uncertain about precedence).
Regarding order of execution/evaluation, that's another term not to confuse with operator precedence. The order of evaluation of the == and != operands in your expression is unspecified, meaning we can't know which one that will get executed first.
In this case it doesn't matter, but if we had this check = a() == b() != c();, it could have. Here, we can't know which of the 3 functions that are executed first. We only know that operator precedence says that the result of a should be compared with the result of b before the result of c, but the function c may still be executed first.
Two things:
The equality operators have same precedence and left to right associativity, so (2 ==2 != 3) is the same as ((2 == 2) != 3) which is (1 != 3) which is true.
The equality operations return an int value as result, so using a _Bool (or, bool with stdbool.h) is not necessary.

Bitwise OR vs Logical OR

in C, is
if((d[i] != 1) && (d[i] != 2))
same as
if(d[i] != (1 | 2))
and why is
if(d[i] != (1 || 2))
rejected by the compiler?
is there a way to simplify the first statement, if I want to check for many constants? which to say check whether d[i] is 1,2,3,4,5. So I would reject it if d[i] is e.g. 6.
1) No. 1 | 2 is 3 (you can test this by printing it out) so if(d[i] != (1 | 2)) does the same thing as if(d[i] != 3)
2) It shouldn't be. 1 || 2 should be 1, so if(d[i] != (1 || 2)) should do the same thing as if(d[i] != 1). If you get an error for this, then I suspect that's because you're using your compiler's "treat warnings as errors" option (-Werror for gcc or clang).
No, They are not same. if((d[i] != 1) && (d[i] != 2)) cannot be further simplified.
Lets come to other codes. if(d[i] != (1 | 2)) it first performs (1|2), which results in 3. and then performs comparison if(d[i] != 3), you certainly don't want that, right?
Now In if(d[i] != (1 || 2)) , first operation done is (1 || 2) it results in true (type is boolean) and your statement effectively becomes if(d[i] != true) //comparing int to boolean, due to type mismatch compiler warns against it.
If you want to check for multiple numbers, use a for loop and array as
int constants[]= {1,2,3,4,5}; //constants to check against
int ar_size = sizeof(constants) / sizeof(constants[0]); //ar_size will adjust to array size, you can use vector for simplification
bool inArray = false; //default is false.
for (int it_i = 0; i < ar_size; it_i++)
{
if (constants[it_i] == d[i]) //Checking is done here
inArray = true;
}
//just use inArray to find if element was in constants[] or not
if (inArray)
{
//code
}
To check a variable against multiple values, the variable must be specified each time as in a == 1 || a == 2 || ... or a != 1 && a != 2 && ....
Specifying only constants as in a != (1 || 2 ||..) will not give the expected result, because 1 || 2 is expanded to 1 (Refer to Short circuit evaluation). Compiler may give warning because it looks like an unlikely (unintended) construct.
Condition 1.
if((d[i] != 1) && (d[i] != 2))
This will check both condition d[i] !=1 and d[i]!=2 that is if d[i] not equal to 1 and 2 condition will run.
If first condition fails it will not check d[i] != 2.
Condition 2.
if(d[i] != (1 | 2))
here (1 | 2) will return 3.
1==> 0001
2==> 0010
------
Bitwise OR= 0011 ==> result will be 3
means it will check d[i] !=3
Condition 3.
if(d[i] != (1 || 2))
1||2 will return TRUE so it will give you error.
as d[i] is having integer value and you are trying to compare it with Boolean value which cause error.
d[i] is integral value, and result of (1 || 2) is boolean true. Comparison of boolean and integral value in if(d[i] != (1 || 2)) makes no sense to compiler.
In a 8-bit number, 1 is represented as:
0000 0001
2 is represented as
0000 0010
The bitwise OR of those two numbers results in
0000 0011
which is 3.
Hence,
d[i] != (1 | 2) is the same as d[i] != 3. That is, obviously, very different from (d[i] != 1) && (d[i] != 2).
if(d[i] != (1 || 2))
should not be rejected by the compiler. That statement is equivalent to:
if(d[i] != 1)
Updated answer
is there a way to simplify the first statement, if I want to check for
many constants? which to say check whether d[i] is 1,2,3,4,5. So I
would reject it if d[i] is e.g. 6.
Absolutely:
if ((d[i] >= 1) && (d[i] <= 5))
See, it's really not that complicated. The compiler can likely optimize the heck out of this.
For what it's worth, detecting x in [1..5] is actually a very difficult expression to optimize with bitmask logic. If you write out a Karnaugh Map for the lower three bits of the integer range, nothing helpful shows up. The best I could simplify it to is this:
if (4 >= (unsigned)(d[i]-1))
I compiled some code in Visual Studio to see how it would optimize (x >= 1) && (x <= 5) in a retail build. It optimizes exactly like the expression above. That is: ((x-1) < 4)
In C if((d[i] != 1) && (d[i] != 2)) implies that this condition is true if and only if d[i] is neither equal to 1 nor d[i] is equal to 2(Both conditions have to be satisfied simultaneously).
which is not same as if(d[i] != (1 | 2)) as this implies that this condition is true if and only if d[i] is not equal to bitwise OR of 1 and 2 which is 0001|0010=0011 (3).So indirectly it is checking if d[i] is not equal to 3.
if(d[i] != (1 || 2)) is not rejected by compiler try gcc <filename.c> and execute the a.out file. This will check d[i] with exclusive OR of 1 and 2 which is 1.So indirectly this condition evaluates to if d[i] is not equal to 1.
Coming to your final question your condition can be easily evaluated by this check:
if((d[i]>=1) && (d[i]<=5)) where 1 is the initial value and 5 is the final value of your check.

Confusion with Associativity of Assignment operator in C

As we all know that Associativity of assignment operator is from right to left but
in the given code output should be zero if we go from right to left but output is 1 .
main()
{
int a=3,b=2;
a=a==b==0;
printf("%d",a);
}
How output is coming out to be 1 if we go by right to letf??
If we go by right to left then (b==0) should be Evaluated first and gives result 0 and then expression (a==0) is Evaluated also gives 0 and at last a's value will be 0.
Assignment is done RTL, but equality (==) isn't.
The statement is actually:
a = ((a == b) == 0)
The right hand side of the assignment is evaluated from left to right. In steps, this is what's happening:
a == b is 0
0 == 0 is 1
1 is assigned to a
Your code is equivalent to :
a = ((a == b) == 0);
Note, this is phrased this way as it was merged from this question. OP asked why a==b==c is equivalent to a==b && b==c in Objective C (which is a strict superset of C). I asked this answer to be migrated since it cites the specificatio where other answers here do not.
No, it is not, it's like (a==b) == c.
Let's look at a simple counter example to your rule:
(0 == 0 == 0);// evaluates to 0
However
(0 == 0) && (0 == 0) // evaluates to 1
The logic is problematic since:
(0 == 0 == 0) reads out as ((0 == 0) == 0) which is similar to 1 == 0 which is false (0).
For the ambitious student
A little dive on how this is evaluated. Programming languages include grammar which specifies how you read a statement in the language. Siance Objective-C does not have an actual specification I'll use the C specificification since objective-c is a strict superset of c.
The standard states that an equality expression (6.5.9) is evaluated as the following:
Equality Expression:
relational-expression
equality-expression == relational-expression
equality-expression != relational-expression
Our case is the second one, since in a == b == c is read as equality_expression == relational_expression where the first equality expression is a == b.
(Now, the actual result number follow quite a way back to a number literal, equality->relational->shift->additive->multiplicative->cast->unary->postfix->primary->constant , but that's not the point)
So the specification clearly states that a==b==c does not evaluate the same way as a==b && b==c
It's worth mentioning that some languages do support expressions in the form a<b<c however, C is not one such language.

What is the point of the logical operators in C?

I was just wondering if there is an XOR logical operator in C (something like && for AND but for XOR). I know I can split an XOR into ANDs, NOTs and ORs but a simple XOR would be much better. Then it occurred to me that if I use the normal XOR bitwise operator between two conditions, it might just work. And for my tests it did.
Consider:
int i = 3;
int j = 7;
int k = 8;
Just for the sake of this rather stupid example, if I need k to be either greater than i or greater than j but not both, XOR would be quite handy.
if ((k > i) XOR (k > j))
printf("Valid");
else
printf("Invalid");
or
printf("%s",((k > i) XOR (k > j)) ? "Valid" : "Invalid");
I put the bitwise XOR ^ and it produced "Invalid". Putting the results of the two comparisons in two integers resulted in the 2 integers to contain a 1, hence the XOR produced a false. I've then tried it with the & and | bitwise operators and both gave the expected results. All this makes sense knowing that true conditions have a non zero value, whilst false conditions have zero values.
I was wondering, is there a reason to use the logical && and || when the bitwise operators &, | and ^ work just the same?
You don't need logical XOR, I have forgotten the SO question, but it's similar to what you're thinking, basically we don't need XOR, it's equivalent to != anyway
FALSE XOR FALSE == FALSE
FALSE XOR TRUE == TRUE
TRUE XOR FALSE == TRUE
TRUE XOR TRUE == FALSE
FALSE != FALSE == FALSE
FALSE != TRUE == TRUE
TRUE != FALSE == TRUE
TRUE != TRUE == FALSE
I'll search my favorites, and paste here the link later...
The bitwise operators do not work "just the same" as the && and || operator. For a start, && and || perform short-circuited evaluation, whereas the the bitwise operators do not. In other words, you can't do something like this with the bitwise operators:
int * p = 0;
(p != 0) && (*p = 1);
because if you said:
(p != 0) & (*p = 1);
both subexpressions would be evaluated, and you would dereference the null pointer.
Bitwise XOR does not work as would a logical XOR when its operands are integer values:
2^4 ? "Valid" : "Invalid"
gives "Valid" but should give "Invalid"
In C arguments of logical operators are treated as Boolean values - anything zero is treated as "false", and anything else (yes, negative values too) are "true". Bitwise ops work on individual bits, and as Neil already noted, are not subject to short-circuit evaluation as logical ops are.
In your example the results are totally valid and expected since bit-wise xor between two ones is zero.
If you want a logical xor operator in C, then you can use this:
#define xor != 0 ^ !!
It works by converting both sides of the expression to booleans and xoring them.
You can use it as if you were using && or ||, like this:
if (a xor b)
AFAICT, there aren't any problems with it.

Resources