Take the 2-minute tour ×
Programming Puzzles & Code Golf Stack Exchange is a question and answer site for programming puzzle enthusiasts and code golfers. It's 100% free, no registration required.

Is it possible to write a C program that multiplies two numbers without using the multiplication and addition operators?

I found this on Stack Overflow. Please help this poor programmer with his problem. And please don't give answers like c = a/(1/((float)b)), which is exactly the same as c = a*b. (And is already given as an answer.)

The answer with the most upvotes on January 19th 2014 wins.

Note: This is a question. Please do not take the question and/or answers seriously. More information is in code-trolling.

share|improve this question
2  
@PaulR use your fantasy –  Jan Dvorak yesterday
13  
Code-golf.SE should not be a place for you to mock questions you've seen on StackOverflow. –  Gareth yesterday
2  
@Gareth, are you sure? The first line of this suggests this may be quite appropriate. –  Darren Stone yesterday
1  
@Gareth, I certainly didn't intend to be mean with my comment. I wrestle with the spirit and noise that code-trolling questions bring, but OP has tagged the question correctly and code-trolling is based on jest and mockery of real questions. –  Darren Stone yesterday
6  
This question isn't as ridiculous as it sounds. Actual computer hardware (transistors) don't have multiply and add operations -- they have basic logic operations like NOT, AND, OR, XOR. Figuring out how to answer this question can give you excellent insight into how a computer really works at the level of logic gates. –  Gabe 23 hours ago
show 11 more comments

18 Answers

Always use recursion

Recusion is the right way!

int inc(int x) {
    return x&1?inc(x>>1)<<1:x|1;
}

int dec(int x) {
    return x&1?x^1:dec(x>>1)<<1|1;
}

int add(int x, int y) {
    return x?add(dec(x),inc(y)):y;
}

int mul(int x, int y) {
    return x?x^1?add(y,mul(dec(x),y)):y:0;
}

int main() {
    int a, b;
    scanf("%i\n%i", &a, &b);
    printf("%i", mul(a,b));
}
share|improve this answer
2  
I would give +3 if I could: one for the ultimate recursion, one for ??:: without parentheses, one for solving the problem without trying to tweak the rules ;) –  tohecz yesterday
1  
The sheer elegance of this has dissuaded me from posting my ripple carry adder based solution. Bit-wise addition by recursion. Wow. –  Julie in Austin yesterday
 
Wow. Nice increment operator, more readable than mine :-) –  Jan Dvorak yesterday
 
If Picasso was a programmer... –  R Hughes 23 hours ago
 
+ can be made of two -s, so add is not necessary (only if you must deal with unsigned integers) –  Sarge Borsch 21 hours ago
show 1 more comment

If you are OK with a little imprecision, you can use the Monte Carlo method:

#include <stdlib.h>
#include <stdio.h>

unsigned int mul(unsigned short a, unsigned short b) {
  const int totalBits = 24;
  const int total = (1 << totalBits);
  const int maxNumBits = 10;
  const int mask = (1 << maxNumBits) - 1;
  int count = 0, i;
  unsigned short x, y;
  for(i = 0; i < total; i++) {
    x = random() & mask;
    y = random() & mask;
    if ((x < a) && (y < b))
      count++;
  }
  return ((long)count) >> (totalBits - (maxNumBits << 1));
}

void main(int argc, char *argv[]) {
  unsigned short a = atoi(argv[1]);
  unsigned short b = atoi(argv[2]);
  printf("%hd * %hd = %d\n", a, b, mul(a, b));
}

Example:

$ ./mul 300 250
300 * 250 = 74954

I guess this could be good enough ;)

share|improve this answer
1  
You have my up vote. I heard Monte Carlo is what NASA uses for its arithmetic. But I'd like to see this without the two instances of the ++ operator. –  Darren Stone yesterday
 
@DarrenStone -= -1 –  Timtech yesterday
4  
@Timtech |= 1 (will work on 50% of numbers, 100% of the time) –  Darren Stone yesterday
 
+1 for the exceptional idea. –  zinking 14 mins ago
add comment

You'll have to compile the program each time, but it does do multiplication of any integers exactly in any version of C or C++.

 #define A 45  // first number
 #define B 315 // second number

 typedef char buffer[A][B];

 main() {
    printf("%d\n",sizeof(buffer));
 }
share|improve this answer
1  
Put it inside a structure and you don't need memory. –  Ben Jackson yesterday
 
Inside a structure definition. A structure might still allocate space in the BSS segment. –  Julie in Austin yesterday
 
I updated my answer to use a typedef. A struct would use memory too. I think @BenJackson was thinking of a named struct without a variable allocated, ie struct a { char buffer[a][b];} and sizeof(struct a). –  Mark Lakata yesterday
 
Hahahah great!! –  Almo 21 hours ago
add comment

Unfortunately, this only works for integers.

Since addition is disallowed, let's build an increment operator first:

int plusOne(int arg){
  int onMask = 1;
  int offMask = -1;
  while (arg & onMask){
    onMask <<= 1;
    offMask <<= 1;
  }
  return(arg & offMask | onMask);
}

Next, we have to handle the sign. First, find the sign bit:

int signBit = -1;
while(signBit << 1) signBit <<=1;

Then take the sign and magnitude of each argument. To negate a number in a two's complement, invert all bits, and add one.

int signA = a & signBit;
if(signA) a = plusOne(-1 ^ a);
int signB = b & signBit;
if(signB) b = plusOne(-1 ^ b);
int signRes = signA ^ signB;

To multiply two positive integers, we can use the geometrical meaning of multiplication:

// 3x4
//
// ooo
// ooo
// ooo
// ooo

int res = 0;
for(int i = 0; i < a; i = plusOne(i))
  for(int j = 1; j < b; j = plusOne(j))
    res = plusOne(res);

if(signRes) res = plusOne(-1 ^ res);

trolls:

  • Addition is disallowed, but does a++ really count as addition? I bet the teacher intended to allow it.
  • Relies on two's complement, but that's an implementation-defined behavior and the target platform wasn't specified.
  • Similarly, assumes subtraction and division are disallowed just as well.
  • << is actually multiplication by a power of two, so it should technically be disallowed.
  • unneccesary diagram is unneccesary. Also, it could have been transposed to save one line.
  • repeated shifting of -1 is not the nicest way of finding the sign bit. Even if there was no built-in constant, you could do a logical shift right of -1, then invert all bits.
  • XOR -1 is a not the best way to invert all bits.
  • The whole charade with sign-magnitude representation is unneccesary. Just cast to unsigned and modular arithmetic will do the rest.
  • since the absolute value of MIN_INT (AKA signBit) is negative, this breaks for that value. Luckily, it still works in half the cases, because MIN_INT * [even number] should be zero. Also, plusOne breaks for -1, causing infinite loops anytime the result overflows. plusOne works just fine for any value. Sorry for the confusion.
share|improve this answer
 
+1 for an actual code troll: It looks like it should work, but it very likely will blow up on the OP and s/he'll have no idea why. –  Kevin yesterday
1  
It's possible to do addition without ANY addition operators by just using shift, XOR and AND. All these ++'s are making my head hurt -- single bit ADD with carry is (x ^ y) | ((x & y) << 1) (modulo any errors caused by typing in this crappy little text box.) –  Julie in Austin yesterday
 
@JulieinAustin yep. The algorithm is even more inefficient than it needs to be. Should I amend the troll list? :-) –  Jan Dvorak yesterday
1  
@JulieinAustin (x ^ y) | ((x & y) << 1) doesn't quite work, it won't propagate carry when x or y and carry are both true in the same position :) –  hobbs yesterday
 
@hobbs solution: instead of ORing, add them recursively if carry is non-zero. –  Jan Dvorak 22 hours ago
show 1 more comment

Why, let's do a recursive halving search between INT64_MIN and INT64_MAX!

#include <stdio.h>
#include <stdint.h>

int64_t mul_finder(int32_t a, int32_t b, int64_t low, int64_t high)
{
    int64_t result = (low - (0 - high)) / 2;
    if (result / a == b && result % a == 0)
        return result;
    else
        return result / a < b ?
            mul_finder(a, b, result, high) :
            mul_finder(a, b, low, result);
}

int64_t mul(int32_t a, int32_t b)
{
    return a == 0 ? 0 : mul_finder(a, b, INT64_MIN, INT64_MAX);
}

void main(int argc, char* argv[])
{
    int32_t a, b;
    sscanf(argv[1], "%d", &a);
    sscanf(argv[2], "%d", &b);
    printf("%d * %d = %ld\n", a, b, mul(a, b));
}

P.S. It will happily sigsegv with some values. ;)

share|improve this answer
add comment

Here's a simple shell script to do it:

curl "http://www.bing.com/search?q=$1%2A$2&go=&qs=n&form=QBLH&pq=$1%2A$2" -s \
| sed -e "s/[<>]/\n/g" \
| grep "^[0-9 *]*=[0-9 ]*$"

UPDATE: Of course, to do it in C, just wrap it in exec("bash", "-c", ...). (Thanks, AmeliaBR)

share|improve this answer
4  
I can't decide which is more awful. That you're outsourcing your calculation to a search engine, or that your chosen search engine is Bing. Unfortunately, I don't think this will work for our happless OP, who needed something in C. –  AmeliaBR yesterday
1  
Thanks for catching that oversight. FYI, I'm using Bing because Google makes it more complicated to issue requests like this -- you have to add headers to convince Google your request is really coming from a browser. –  Vroo yesterday
add comment

Since you didn't specify what size of number, I assume that you mean two one-bit numbers.

_Bool mul(_Bool a, _Bool b) {
    if (a && b) {
        return 1;
    } else {
        return 0;
    }
}
share|improve this answer
 
Nice. A deliberate misinterpretation of the question :-) –  Jan Dvorak yesterday
 
You can optimize this to return a && b;. It’s shorter, so it’s faster. –  minitech 12 hours ago
 
@minitech: I decided against that in order to make the code slightly worse. If I wanted to go further with that, I'd make it return a&b;. –  col6y 10 hours ago
add comment

My troll solution for unsigned int:

#include<stdio.h>

unsigned int foo(unsigned int x, unsigned int y)
{
  unsigned int t,c=0;
  do {
    t = c;
    c = (x & y) | (x & c) | (y & c);
    c <<= 1;
  } while (c!=t);
  return x^y^c;
}


unsigned int bar(unsigned int x,unsigned int y)
{
  unsigned int r=0;
  while (y != 0) {
    if (y & 1) r = foo(r,x);
    y>>=1;
    x<<=1;
  }
  return r;
}

int main(int c, char** param)
{
  unsigned int x,y;
  if (c!=3) {
     printf("Fuck!\n");
     return 1;
  }
  sscanf(param[1],"%ud",&x);
  sscanf(param[2],"%ud",&y);
  printf("%d\n", bar(x,y));
  return 0;
}
share|improve this answer
 
+1 Nice implementation of carry evaluation. I like your code :) –  tohecz 17 hours ago
add comment
#include <stdio.h>
#include <stdlib.h>

int mult (int n1, int n2);
int add (int n1, int n2 );
int main (int argc, char** argv)
{
        int a,b;
        a = atoi(argv[1]);
        b = atoi(argv[2]);

        printf ("\n%i times %i is %i\n",a,b,mult(a,b));
        return 0;
}

int add (int n1, int n2 )
{
        return n1 - -n2;
}

int mult (int n1, int n2)
{
        int sum = 0;
        char s1='p', s2='p';
        if ( n1 == 0 || n2 == 0 ) return 0;
        if( n1 < 0 )
        {
                s1 = 'n';
                n1 = -n1;
        }
        if( n2 < 0 )
        {
                s2 = 'n';
                n2 = -n2;
        }
        for (int i = 1; i <= n2; i = add( i, 1 ))
        {
                sum = add(sum,  n1);
        }
        if ( s1 != s2 ) sum = -sum;
        return sum;
}
share|improve this answer
add comment

Unfortunately, multiplication is a very difficult problem in computer science. The best solution is to use division instead:

#include <stdio.h>
#include <limits.h>
int multiply(int x, int y) {
    int a;
    for (a=INT_MAX; a>1; a--) {
        if (a/x == y) {
            return a;
        }
    }
    for (a=-1; a>INT_MIN; a--) {
        if (a/x == y) {
            return a;
        }
    }
    return 0;
}
main (int argc, char **argv) {
    int a, b;
    if (argc > 1) a = atoi(argv[1]);
    else a = 42;
    if (argc > 2) b = atoi(argv[2]);
    else b = 13;
    printf("%d * %d is %d\n", a, b, multiply(a,b));
}
share|improve this answer
add comment

In real life I usually respond to trolling with knowledge, so here's an answer that doesn't troll at all. It works for all int values as far as I can see.

int multiply (int a, int b) {
  int r = 0;
  if (a < 0) { a = -a; b = -b }

  while (a) {
    if (a&1) {
      int x = b;
      do { int y = x&r; r ^= x; x = y<<1 } while (x);
    }
    a>>=1; b<<=1;
  }
  return r;
}

This is, to the best of my understanding, very much like how a CPU might actually do integer multiplication. First, we make sure that at least one of the arguments (a) is positive by flipping the sign on both if a is negative (and no, I refuse to count negation as a kind of either addition or multiplication). Then the while (a) loop adds a shifted copy of b to the result for every set bit in a. The do loop implements r += x using and, xor, and shifting in what's clearly a set of half-adders, with the carry bits fed back into x until there are no more (a real CPU would use full adders, which is more efficient, but C doesn't have the operators we need for this, unless you count the + operator).

share|improve this answer
3  
The asker didn't troll. You are supposed to troll. –  Jan Dvorak yesterday
add comment

I'm not sure what constitutes "cheating" in these "code troll" posts, but this multiplies 2 arbitrary integers, at run time, with no * or + operator using standard libraries (C99).

#include <math.h>
main()
{
  int a = 6;
  int b = 7;
  return fma(a,b,0);
}
share|improve this answer
add comment

Works for floating point numbers as well:

float mul(float a, float b){
  return std::exp(std::log(a) - std::log(1.0 / b));
}
share|improve this answer
add comment
unsigned add( unsigned a, unsigned b )
{
    return (unsigned)&((char*)a)[b];  // ignore compiler warnings
       // (if pointers are bigger than unsigned). it still works.
}
unsigned umul( unsigned a, unsigned b )
{
    unsigned res = 0;
    while( a != 0 ){
        if( a & 1) res = add( res, b );
        b <<= 1;
        a >>= 1;
    }
    return res;
}

int mul( int a, int b ){
    return (int)umul( (unsigned)a, (unsigned)b );
}

If you consider the a[b] hack to be cheating (since it's really an add) then this works instead. But table lookups involve pointer adds too.

See http://en.wikipedia.org/wiki/IBM_1620

static unsigned sumtab[17][16]= {
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15},
{ 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16},
{ 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17},
{ 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18},
{ 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19},
{ 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19,20},
{ 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19,20,21},
{ 7, 8, 9,10,11,12,13,14,15,16,17,18,19,20,21,22},
{ 8, 9,10,11,12,13,14,15,16,17,18,19,20,21,22,23},
{ 9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24},
{10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25},
{11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26},
{12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27},
{13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28},
{14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29},
{15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30},
{16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31}
};

unsigned add( unsigned a, unsigned b )
{
   static const int add4hack[8] =  4,8,12,16,20,24,28,32};
   unsigned carry = 0;
   unsigned (*sumtab0)[16] = &sumtab[0];
   unsigned (*sumtab1)[16] = &sumtab[1];
   unsigned result = 0;
   int nshift = 0;
   while( (a|b) != 0 ){
      unsigned psum = (carry?sumtab1:sumtab0)[ a & 0xF ][ b & 0xF ];
      result = result | ((psum & 0xF)<<nshift);
      carry = psum >> 4;
      a = a >> 4
      b = b >> 4;
      nshift= add4hack[nshift>>2];  // add 4 to nshift.
   }
   return result;
}
share|improve this answer
 
Oops, there is * char (although it's not multiplication) –  Sarge Borsch 21 hours ago
add comment

C#

I think subtraction and negation are not allowed... Anyway:

int mul(int a, int b)
{
    int t = 0;
    for (int i = b; i >= 1; i--) t -= -a;
    return t;
}
share|improve this answer
add comment

Throwing this into the mix:

#include <stdio.h>
#include <stdlib.h>

int mul(int a, int b)
{
        asm ("mul %2"
            : "=a" (a)
            : "%0" (a), "r" (b) : "cc"
        );
        return a;
}

int main(int argc, char *argv[])
{
        int a, b;

        a = (argc > 1) ? atoi(argv[1]) : 0;
        b = (argc > 2) ? atoi(argv[2]) : 0;

        return printf("%d x %d = %d\n", a, b, mul(a, b)) < 1;
}
share|improve this answer
1  
"without using the multiplication and addition operators". Nice bending of the rules - this will be absolutely useless to the asker :-) –  Jan Dvorak 20 hours ago
add comment

Since all computers are essentially adding machines, with flow control, comparators, and about every other operation including incrementing the program counter dependent on addition then no, in the strictest sense this program can't be written, at least not for any non-analogue computer.

share|improve this answer
add comment
 int bogomul(int A, int B)
{
    int C = 0;
    while(C/A != B)
    {

        print("Answer isn't: %d", C);
        C = rand();

    }
    return C;
}
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.