multiply two numbers using only bit operations - c

While learning Bit operations in c,I was searching for code to multiply two numbers using only bit operations , I found the following code!. I am unable to understand how ternary operator is working in the following scenario and producing the correct o/p.
#include<stdio.h>
static int multiply (int x, int y)
{
return y==0?0:((y&1) ==1?x:0)+multiply(x<<1,y>>1);
}
int main()
{
printf("%d",multiply(2,3));
return 0;
}
Can someone please explain how is the above code working?.

That is not using "only bit operations", since it's using + to add numbers.
Maybe indenting can help break up the complicated expression:
return (y == 0 ? 0
: (y & 1) == 1 ? x
: 0)
+ multiply(x << 1, y >> 1);
Basically it's a recursive addition, that stops when y reaches 0. If the least significant bit of y is set, x is added to the result, else it is not. On each recursion, one bit of y is dropped so that it eventually will reach 0. The value of x is shifted to the left, very much like when doing multiplication by hand.
For instance if x = 3 (binary 11) and y = 6 (binary 110), it will compute
0 * 3 + 1 * 6 + 1 * 12 = 18
And of course 18 is 3 * 6.
Each recursion step is written as a * b where a is the least significant bit of y at that step (reading from the left, you get 0, 1, 1 which is the bits of y starting with the least significant bit) and b is the value of x at that step.

If y is odd, x * y = x + (x * 2) * (y / 2)
If y is even, x * y = (x * 2) * (y / 2)
With the logic above, and use recursion until y = 0.

If you are struggling understanding a complex nested use of the conditional operator, then simply expand it to an if statement:
static int multiply (int x, int y)
{
if (y==0)
return 0;
else
return ((y&1) ==1?x:0)+multiply(x<<1,y>>1);
}
And then expand the inner conditional operator:
static int multiply (int x, int y)
{
if (y == 0)
return 0;
else if ((y&1) == 1)
return x + multiply(x<<1, y>>1);
else return
return multiply(x<<1, y>>1);
}
Once you've expanded it like this, it should be clear what the expression is doing.

Related

Writing a function that calculates the sum of squares within a range in one line in C

My try
double sum_squares_from(double x, double n){
return n<=0 ? 0 : x*x + sum_squares_from((x+n-1)*(x+n-1),n-1);
}
Instead of using loops my professor wants us to write functions like this...
What the exercise asks for is a function sum_squares_from() with double x being the starting number and n is the number of number. For example if you do x = 2 and n = 4 you get 2*2+3*3+4*4+5*5. It returns zero if n == 0.
My thinking was that in my example what I have is basically x*x+(x+1)(x+1)+(x+1+1)(x+1+1)+(x+1+1+1)(x+1+1+1) = (x+0)(x+0)+(x+1)(x+1)+(x+2)(x+2)+(x+3)(x+3) = (x+n-1)^2 repeated n times where n gets decremented every time by one until it becomes zero and then you sum everything.
Did I do it right?
(if my professor seems a bit demanding... he somehow does this sort of thing all in his head without auxiliary calculations. Scary guy)
It's not recursive, but it's one line:
int
sum_squares(int x, int n) {
return ((x + n - 1) * (x + n) * (2 * (x + n - 1) + 1) / 6) - ((x - 1) * x * (2 * (x - 1) + 1) / 6);
}
Sum of squares (of integers) has a closed-form solution for 1 .. n. This code calculates the sum of squares from 1 .. (x+n) and then subtracts the sum of squares from 1 .. (x-1).
The original version of this answer used ASCII art.
So,
&Sum;i:0..n i = n(n+1)(&half;)
&Sum;i:0..n i2 = n(n+1)(2n+1)(&frac16;)
We note that,
&Sum;i:0..n (x+i)2
&equals; &Sum;i:0...n x2 + 2xi + i2
&equals; (n+1)x2 + (2x)&Sum;i:0..n i + &Sum;i:0..n i2
&equals; (n+1)x2 + n(n+1)x + n(n+1)(2n+1)(&frac16;)
Thus, your sum has the closed form:
double sum_squares_from(double x, int n) {
return ((n-- > 0)
? (n + 1) * x * x
+ x * n * (n + 1)
+ n * (n + 1) * (2 * n + 1) / 6.
: 0);
}
If I apply some obfuscation, the one-line version becomes:
double sum_squares_from(double x, int n) {
return (n-->0)?(n+1)*(x*x+x*n+n*(2*n+1)/6.):0;
}
If the task is to implement the summation in a loop, use tail recursion. Tail recursion can be mechanically replaced with a loop, and many compilers implement this optimization.
static double sum_squares_from_loop(double x, int n, double s) {
return (n <= 0) ? s : sum_squares_from_loop(x+1, n-1, s+x*x);
}
double sum_squares_from(double x, int n) {
return sum_squares_from_loop(x, n, 0);
}
As an illustration, if you observe the generated assembly in GCC at a sufficient optimization level (-Os, -O2, or -O3), you will notice that the recursive call is eliminated (and sum_squares_from_loop is inlined to boot).
Try it online!
As mentioned in my original comment, n should not be type double, but instead be type int to avoid floating point comparison problems with n <= 0. Making the change and simplifying the multiplication and recursive call, you do:
double sum_squares_from(double x, int n)
{
return n <= 0 ? 0 : x * x + sum_squares_from (x + 1, n - 1);
}
If you think about starting with x * x and increasing x by 1, n times, then the simple x * x + sum_squares_from (x + 1, n - 1) is quite easy to understand.
Maybe this?
double sum_squares_from(double x, double n) {
return n <= 0 ? 0 : (x + n - 1) * (x + n - 1) + sum_squares_from(x, n - 1);
}

How to evaluate the Sine Series (Taylor) for value of x using Recursion in C?

(C) calculate series
y = x - x3/3! + x5/5! - x7/7! + .....
where stopping criterion is
| xi/i! | <= 0.001
What I have tried :
#include<stdio.h>
#include<math.h>
int fact(int x){
if(x>1){
return x * fact(x-1);
}
else {
return 1 ;
}
}
int main () {
int x , i=1 , sign=1 ;
float result ;
scanf("%d",&x);
while(abs(pow(x,i)/fact(i))>0.001){
result += sign*(pow(x,i)/fact(i));
i+2;
sign = sign * -1 ;
}
printf("result= %f\n",result);
return 0 ;
}
the problem is
when i input 90 ... the output should be 1 ... ( it's like the sin(x) )
im getting a different output
The code (at least) misses to initialise result.
Change
float result;
to
float result = 0.f;
Also
i+2;
is a NOP (no-operation). It results in nothing. It adds 2 to i and does not assign the result to anything, "throughs away" the result.
To increment i by 2 do:
i = i + 2;
or
i += 2;
Also^2 using abs() won't work as it return int.
Use fabs() to get a floating point value.
Or just do not use it at all as it's argument will never be negative here.
As a final advice prefer using double over float, as floats accurary is limited.
The problem is very clear. You have to convert degree into radian before performing the loop. Your code has some other issues also.
Here is the rectified code, which gives you 1 for 90:
#include<stdio.h>
#include<math.h>
int fact(int x){
if(x>1){
return x * fact(x-1);
}
else {
return 1 ;
}
}
int main () {
int x , i=1 , sign=1;
double result, rad;
scanf("%d",&x);
rad = x/180.0*3.1415;
while((pow(x,i)/fact(i))>0.001){
result += sign*(pow(rad,i)/fact(i));
i+=2;
sign *= -1 ;
}
printf("result= %f\n",result);
return 0 ;
}
sin(90)=0.89399666360055789051826949840421...
Besides the unit confusion, your code is not very efficient, as you compute the powers and factorials from scratch on each term, when a nice recurrence exists.
Sin= x
Term= x
Factor= -x*x
i= 2
while |Term| > 0.001:
Term*= Factor / (i * (i+1))
Sin+= Term
i+= 2
Because of huge cancellation errors, this formula is not appropriate for large values of the argument. My own implementation gives -1.07524337969e+21 for 90.
If you compute it for 90-14*2*Pi instead, you get 0.893995..., not a so bad result.
An algorithm that calculates sin (x) using the following power series: sin (x) = (x / 1!) - (X ^ 3/3) + (x ^ 5/5!) - (! ^ x 7/7) + ... We stop the calculation when the difference between two succesive terms of the sum given is less than a certain tolerance.

Round up a float number that has a non-zero decimal digit

I was asking about round a number half up earlier today and got great help from #alk. In that post, my thinking was to round up 4.5 to 5 but round 4.4 down to 4. And the solution given by #alk was:
int round_number(float x)
{
return x + 0.5;
}
and it works very elegantly!
In this post, I would like to discuss how to implement the ceil() function in C.
Along the same line as the last solution given by #alk, I came up with the following:
int round_up(float y)
{
return y + 0.99999999;
}
This works for all situations except when the the float number y has .00000001. I am wondering if there's any better way to do the same thing as ceil() in C.
Unless you reliably know the epsilon of float (I'm not sure standard C provides that), I think you're stuck with return (y < 0 || y == (int)y) ? y : y + 1;
This fails for negative numbers.
int round_up(float y) {
return y + 0.99999999;
}
But let's use that to our advantage. float to int conversion is a truncate toward 0.0. Thus negative numbers are doing a "round up" or "ceiling" function. When we have a positive float, convert to int noting this is a "floor" function. Adjust when y is not an integer.
(Assume y within INT_MIN ... INT_MAX.)
int ceil(float y) {
if (y < 0) {
return y; // this does a ceiling function as y < 0.
}
int i = y; // this does a floor function as y >= 0.
if (i != y) i++;
return i;
}
void ceil_test(float y) {
printf("%f %d\n", y, ceil(y));
}
The first snippet works incorrectly for negative numbers. -3.5 will be come -3, not -4. To round values properly use
int round_number(float x)
{
if (x >= 0)
return x + 0.5f;
else
return x - 0.5f
}
Even that way it's still incorrect for 2 values. See Why does Math.round(0.49999999999999994) return 1?. Note that you need to use the f suffix to get the float literal, otherwise the operation will be done in double precision and then downcast back to float
For ceiling, adding 1 is enough
int ceiling(float x)
{
if (x < 0 || (int)x == x)
return x;
else
return x + 1.0f;
}
When x is an integer, e.g. x = 3.0 (or -3.0), it returns 3 (or -3). For x = 3.1 it returns 4, for x = -3.1 it returns -3

how to check if the / operator has no remainder in C?

I want to check if the / operator has no remainder or not:
int x = 0;
if (x = 16 / 4), if there is no remainder:
then x = x - 1;
if (x = 16 / 5), if remainder is not zero:
then x = x + 1;
How to check if there are remainder in C? and
How to implement it?
Frist, you need % remainder operator:
if (x = 16 % 4){
printf("remainder in X");
}
Note: it will not work with float/double, in that case you need to use fmod (double numer, double denom);.
Second, to implement it as you wish:
if (x = 16 / 4), if there is no remainder, x = x - 1;
If (x = 16 / 5), then x = x + 1;
Useing , comma operator, you can do it in single step as follows (read comments):
int main(){
int x = 0, // Quotient.
n = 16, // Numerator
d = 4; // Denominator
// Remainder is not saved
if(x = n / d, n % d) // == x = n / d; if(n % d)
printf("Remainder not zero, x + 1 = %d", (x + 1));
else
printf("Remainder is zero, x - 1 = %d", (x - 1));
return 1;
}
Check working codes #codepade: first, second, third.
Notice in if-condition I am using Comma Operator: ,, to understand , operator read: comma operator with an example.
If you want to find the remainder of an integer division then you can use the modulus(%):
if( 16 % 4 == 0 )
{
x = x - 1 ;
}
else
{
x = x +1 ;
}
use the % operator to find the remainder of a division
if (number % divisor == 0)
{
//code for perfect divisor
}
else
{
//the number doesn't divide perfectly by divisor
}
use modulous operator for this purpose.
if(x%y == 0) then there is no remainder.
In division operation, if the result is floating point, then only integer part will be returned and decimal part will be discarded.
you can use Modulous operator which deals with remainder.
The modulus operator (represented by the % symbol in C) computes the remainder. So:
x = 16 % 4;
x will be 0.
X = 16 % 5;
x will be 1

Create method which checks if x + y will overflow using bitwise operations

I need to create a method in C using bitwise operations which checks if x + y will overflow or not. I can only use a maximum of 20 of the following operations; ! ~ & ^ | + << >> Keep in mind I have to test for both negative and positive numbers.
I've tried several times to make it work. Is my logic sound? I'm going by:
if (x + y) is less than x, then it has overflowed. Based on that logic, I wrote this;
int addOK(int x, int y)
{
int sum = x + y;
int nx = ((~x) + 1);
int check = (sum + nx)>>31;
return !check;
}
Thank you!
This should work, but it doesn't use only bitwise operator, but it work for signed :
int addOK(int x, int y)
{
int check;
if (greaterThan(0, x^y))
check = 0;
else if (greaterThan(x, 0))
check = greaterThan(y, INT_MAX -x);
else
check = greaterThan(INT_MIN -x, y);
return check;
}
int greaterThan(int first, int second) {
/* first > second means second - first is less than 0
shift the sign bit and then compare it to 1 */
return (second + (~first +1)) >> ((sizeof(int) * 8) -1) & 1;
}
If the two numbers are both positive should be enough :
int addOK(int x, int y) {
if(x^y < 0)
return 0;
return 1;
}

Resources