703

How would you divide a number by 3 without using *, /, +, -, %, operators?

The number may be signed or unsigned.

14
  • 8
    The identified duplicate isn't a duplicate. Note that several answers here use neither bit shifting or addition since this question didn't restrict a solution to those operations. Commented Jul 28, 2012 at 0:37
  • 4
    BTW: The other question was about checking if a number is divisible by 3. This question is about dividing by 3. Commented Jul 30, 2012 at 13:57
  • 3
    Perhaps the interviewer meant to ask "How do you divide by 2 without using blah blah blah". That would be a sane question that most developers should be able to answer.
    – Sam Elstob
    Commented Aug 9, 2012 at 12:09
  • 4
    x /= 3; does not use the / operator, /= is a different operator.
    – James
    Commented Aug 21, 2012 at 15:13
  • 28
    This question is offtopic to SO. It belongs to codegolf.stackexchange.com
    – Kromster
    Commented Jun 3, 2014 at 4:28

48 Answers 48

555

This is a simple function which performs the desired operation. But it requires the + operator, so all you have left to do is to add the values with bit-operators:

// replaces the + operator
int add(int x, int y)
{
    while (x) {
        int t = (x & y) << 1;
        y ^= x;
        x = t;
    }
    return y;
}

int divideby3(int num)
{
    int sum = 0;
    while (num > 3) {
        sum = add(num >> 2, sum);
        num = add(num >> 2, num & 3);
    }
    if (num == 3)
        sum = add(sum, 1);
    return sum; 
}

As Jim commented this works, because:

  • n = 4 * a + b
  • n / 3 = a + (a + b) / 3
  • So sum += a, n = a + b, and iterate

  • When a == 0 (n < 4), sum += floor(n / 3); i.e. 1, if n == 3, else 0

10
  • 96
    This is probably the answer Oracle is looking for. It shows you know how the +, -, * and / operators are actually implemented on the CPU: simple bitwise operations.
    – craig65535
    Commented Jul 27, 2012 at 21:55
  • 21
    This works because n = 4a + b, n/3 = a + (a+b)/3, so sum += a, n = a + b, and iterate. When a == 0 (n < 4), sum += floor(n/3); i.e., 1 if n == 3, else 0.
    – Jim Balter
    Commented Jul 28, 2012 at 5:36
  • 7
    Here's a trick i found which got me a similar solution. In decimal: 1 / 3 = 0.333333, the repeating numbers make this easy to calculate using a / 3 = a/10*3 + a/100*3 + a/1000*3 + (..). In binary it's almost the same: 1 / 3 = 0.0101010101 (base 2), which leads to a / 3 = a/4 + a/16 + a/64 + (..). Dividing by 4 is where the bit shift comes from. The last check on num==3 is needed because we've only got integers to work with. Commented Jul 30, 2012 at 12:40
  • 4
    In base 4 it gets even better: a / 3 = a * 0.111111 (base 4) = a * 4^-1 + a * 4^-2 + a * 4^-3 + (..) = a >> 2 + a >> 4 + a >> 6 + (..). The base 4 also explains why only 3 is rounded up at the end, while 1 and 2 can be rounded down. Commented Jul 30, 2012 at 13:04
  • 2
    @while1: it's bitwise AND operation. Also, a well-known fact is that for n == 2^k the following is true: x % n == x & (n-1), so here num & 3 is used to perform num % 4 while % is not allowed.
    – aplavin
    Commented Jul 31, 2012 at 20:24
440

Idiotic conditions call for an idiotic solution:

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

int main()
{
    FILE * fp=fopen("temp.dat","w+b");
    int number=12346;
    int divisor=3;
    char * buf = calloc(number,1);
    fwrite(buf,number,1,fp);
    rewind(fp);
    int result=fread(buf,divisor,number,fp);
    printf("%d / %d = %d", number, divisor, result);
    free(buf);
    fclose(fp);
    return 0;
}

If also the decimal part is needed, just declare result as double and add to it the result of fmod(number,divisor).

Explanation of how it works

  1. The fwrite writes number bytes (number being 123456 in the example above).
  2. rewind resets the file pointer to the front of the file.
  3. fread reads a maximum of number "records" that are divisor in length from the file, and returns the number of elements it read.

If you write 30 bytes then read back the file in units of 3, you get 10 "units". 30 / 3 = 10

22
  • 13
    @earlNameless: you don't know what they use inside, they are in the black box of "implementation defined". Nothing stops them to just use bitwise operators; anyway, they are outside the domain of my code, so that's not my problem. :) Commented Jul 29, 2012 at 1:02
  • 8
    @IvoFlipse from I can clean, you get a big something and shove it into something three times too small, and then see how much fitted in. That about is a third. Commented Jul 29, 2012 at 15:00
  • 29
    asked the best C programmer (and most socially awkward) at our company to explain the code. after he did, i said it was pretty ingenious. He said 'this dreck is not a solution' and asked me to leave his desk
    – user1107975
    Commented Jul 30, 2012 at 12:45
  • 6
    @cvursache I think the point is that the question is so brain dead, that a brain dead answer is allowed. The "best C programmer" at your company" could just as easily have said "that dreck is not a (proper) question".
    – JeremyP
    Commented Jul 31, 2012 at 10:18
  • 19
    @JeremyP: exactly. My point is that if in real life I was given a compiler without support for arithmetic the only sensible thing would be to ask for a better compiler, because working in those conditions doesn't make any sense. If the interviewer wanted to check my knowledge of how to implement division with bitwise operations he could just be straightforward and ask it as a theoretical question; these kind of "trick exercises" just scream for answers like this. Commented Jul 31, 2012 at 11:22
310
log(pow(exp(number),0.33333333333333333333)) /* :-) */
4
  • 2
    This might actually work if rounded properly and if the number isn't too large.
    – Mysticial
    Commented Jul 27, 2012 at 19:57
  • 254
    Improved version: log(pow(exp(number),sin(atan2(1,sqrt(8)))))
    – Alan Curry
    Commented Jul 28, 2012 at 0:14
  • @bitmask, math functions are usually implemented directly in asm. Commented Aug 10, 2012 at 9:40
  • 8
    i just typed it in my js console, it doesn't work with a number higher than 709 (may be its just my system) Math.log(Math.pow(Math.exp(709),0.33333333333333333333)) and Math.log(Math.pow(Math.exp(709),Math.sin(Math.atan2(1,Math.sqrt(8)))))
    – Shaheer
    Commented Aug 30, 2012 at 13:12
209
#include <stdio.h>
#include <stdlib.h>

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

    int num = 1234567;
    int den = 3;
    div_t r = div(num,den); // div() is a standard C function.
    printf("%d\n", r.quot);

    return 0;
}
0
113

You can use (platform dependent) inline assembly, e.g., for x86: (also works for negative numbers)

#include <stdio.h>

int main() {
  int dividend = -42, divisor = 5, quotient, remainder;

  __asm__ ( "cdq; idivl %%ebx;"
          : "=a" (quotient), "=d" (remainder)
          : "a"  (dividend), "b"  (divisor)
          : );

  printf("%i / %i = %i, remainder: %i\n", dividend, divisor, quotient, remainder);
  return 0;
}
11
  • 2
    @JeremyP doesn't your comment fail on the assumption that the answer can't be written in C? The question is tagged "C" after all. Commented Aug 1, 2012 at 18:33
  • 1
    @SethCarnegie The answer is not written in C is my point. x86 assembler is not part of the standard.
    – JeremyP
    Commented Aug 2, 2012 at 13:29
  • 1
    @JeremyP that is true, but the asm directive is. And I would add that C compilers are not the only ones that have inline assemblers, Delphi has that as well. Commented Aug 2, 2012 at 18:01
  • 7
    @SethCarnegie The asm directive is only mentioned in the C99 standard under Appendix J - common extensions.
    – JeremyP
    Commented Aug 3, 2012 at 9:49
  • 2
    Fails in arm-eabi-gcc. Commented Jul 26, 2015 at 17:34
107

Use itoa to convert to a base 3 string. Drop the last trit and convert back to base 10.

// Note: itoa is non-standard but actual implementations
// don't seem to handle negative when base != 10.
int div3(int i) {
    char str[42];
    sprintf(str, "%d", INT_MIN); // Put minus sign at str[0]
    if (i>0)                     // Remove sign if positive
        str[0] = ' ';
    itoa(abs(i), &str[1], 3);    // Put ternary absolute value starting at str[1]
    str[strlen(&str[1])] = '\0'; // Drop last digit
    return strtol(str, NULL, 3); // Read back result
}
3
  • 4
    @cshemby I actually didn't know that itoa could use an arbitrary base. If you do a complete working implementation using itoa I'll upvote.
    – Mysticial
    Commented Jul 27, 2012 at 19:54
  • 2
    The implementation will contain / and %... :-) Commented Aug 22, 2012 at 6:39
  • 2
    @R.. So does the implementation of printf for displaying your decimal result. Commented Sep 21, 2016 at 16:39
57

(note: see Edit 2 below for a better version!)

This is not as tricky as it sounds, because you said "without using the [..] + [..] operators". See below, if you want to forbid using the + character all together.

unsigned div_by(unsigned const x, unsigned const by) {
  unsigned floor = 0;
  for (unsigned cmp = 0, r = 0; cmp <= x;) {
    for (unsigned i = 0; i < by; i++)
      cmp++; // that's not the + operator!
    floor = r;
    r++; // neither is this.
  }
  return floor;
}

then just say div_by(100,3) to divide 100 by 3.


Edit: You can go on and replace the ++ operator as well:

unsigned inc(unsigned x) {
  for (unsigned mask = 1; mask; mask <<= 1) {
    if (mask & x)
      x &= ~mask;
    else
      return x & mask;
  }
  return 0; // overflow (note that both x and mask are 0 here)
}

Edit 2: Slightly faster version without using any operator that contains the +,-,*,/,% characters.

unsigned add(char const zero[], unsigned const x, unsigned const y) {
  // this exploits that &foo[bar] == foo+bar if foo is of type char*
  return (int)(uintptr_t)(&((&zero[x])[y]));
}

unsigned div_by(unsigned const x, unsigned const by) {
  unsigned floor = 0;
  for (unsigned cmp = 0, r = 0; cmp <= x;) {
    cmp = add(0,cmp,by);
    floor = r;
    r = add(0,r,1);
  }
  return floor;
}

We use the first argument of the add function because we cannot denote the type of pointers without using the * character, except in function parameter lists, where the syntax type[] is identical to type* const.

FWIW, you can easily implement a multiplication function using a similar trick to use the 0x55555556 trick proposed by AndreyT:

int mul(int const x, int const y) {
  return sizeof(struct {
    char const ignore[y];
  }[x]);
}
12
  • 5
    The question is tagged c, not SQL, even though Oracle is mentioned.
    – bitmask
    Commented Jul 27, 2012 at 19:48
  • 3
    This does indeed not look like SQL!
    – moooeeeep
    Commented Jul 27, 2012 at 19:49
  • 65
    If you can use ++: Why aren't you simply use /=?
    – qwertz
    Commented Jul 27, 2012 at 20:10
  • 5
    @bitmask: ++ is also a shortcut: For num = num + 1.
    – qwertz
    Commented Jul 27, 2012 at 20:17
  • 4
    @bitmask Yeah, but += is finally a shortcut for num = num + 1.
    – qwertz
    Commented Jul 27, 2012 at 20:23
43

It is easily possible on the Setun computer.

To divide an integer by 3, shift right by 1 place.

I'm not sure whether it's strictly possible to implement a conforming C compiler on such a platform though. We might have to stretch the rules a bit, like interpreting "at least 8 bits" as "capable of holding at least integers from -128 to +127".

2
  • 8
    The problem is that you don't have a "shift right by 1 place" operator in C. The >> operator is the "division by 2^n" operator, i.e. it is specified in terms of arithmetic, not machine representation. Commented Aug 22, 2012 at 6:44
  • The Setun computer is not binary in any sense of the word, so the instruction set must be definitely different. However, I am not at all familiar with the operation of that computer, so I cannot confirm if the response is really correct - but at least it makes sense - and is highly original. +1
    – virolino
    Commented Feb 7, 2019 at 6:57
34

Here's my solution:

public static int div_by_3(long a) {
    a <<= 30;
    for(int i = 2; i <= 32 ; i <<= 1) {
        a = add(a, a >> i);
    }
    return (int) (a >> 32);
}

public static long add(long a, long b) {
    long carry = (a & b) << 1;
    long sum = (a ^ b);
    return carry == 0 ? sum : add(carry, sum);
}

First, note that

1/3 = 1/4 + 1/16 + 1/64 + ...

Now, the rest is simple!

a/3 = a * 1/3  
a/3 = a * (1/4 + 1/16 + 1/64 + ...)
a/3 = a/4 + a/16 + 1/64 + ...
a/3 = a >> 2 + a >> 4 + a >> 6 + ...

Now all we have to do is add together these bit shifted values of a! Oops! We can't add though, so instead, we'll have to write an add function using bit-wise operators! If you're familiar with bit-wise operators, my solution should look fairly simple... but just in-case you aren't, I'll walk through an example at the end.

Another thing to note is that first I shift left by 30! This is to make sure that the fractions don't get rounded off.

11 + 6

1011 + 0110  
sum = 1011 ^ 0110 = 1101  
carry = (1011 & 0110) << 1 = 0010 << 1 = 0100  
Now you recurse!

1101 + 0100  
sum = 1101 ^ 0100 = 1001  
carry = (1101 & 0100) << 1 = 0100 << 1 = 1000  
Again!

1001 + 1000  
sum = 1001 ^ 1000 = 0001  
carry = (1001 & 1000) << 1 = 1000 << 1 = 10000  
One last time!

0001 + 10000
sum = 0001 ^ 10000 = 10001 = 17  
carry = (0001 & 10000) << 1 = 0

Done!

It's simply carry addition that you learned as a child!

111
 1011
+0110
-----
10001

This implementation failed because we can not add all terms of the equation:

a / 3 = a/4 + a/4^2 + a/4^3 + ... + a/4^i + ... = f(a, i) + a * 1/3 * 1/4^i
f(a, i) = a/4 + a/4^2 + ... + a/4^i

Suppose the reslut of div_by_3(a) = x, then x <= floor(f(a, i)) < a / 3. When a = 3k, we get wrong answer.

5
  • 2
    does it work for input of 3? 1/4, 1/16, ... all return 0 for 3, so would sum to 0, but 3/3 = 1. Commented Jul 27, 2012 at 21:55
  • 1
    The logic is good but the implementation is problematic. The series approximation of n/3 is always less than n/3 which means that for any n=3k the result would be k-1 instead of k.
    – Xyand
    Commented Jul 28, 2012 at 0:40
  • @Albert, This was the first approach I tried, with a couple variations, but they all failed on either certain numbers evenly divisible by 3 or evenly divisible by 2 (depending on the variation). So I tried something more straightforward. I would like to see an implementation of this approach that works, to see where I was screwing up. Commented Jul 28, 2012 at 0:53
  • @hatchet, The question is closed so I can't post a new answer but the idea is to implement binary div. I should be easy to look it up.
    – Xyand
    Commented Jul 28, 2012 at 17:06
25

To divide a 32-bit number by 3 one can multiply it by 0x55555556 and then take the upper 32 bits of the 64 bit result.

Now all that's left to do is to implement multiplication using bit operations and shifts...

3
  • 1
    This is a common compiler trick to work around slow divisions. But you probably need to do some fix ups, since 0x55555556/2**32 isn't exactly 1/3. Commented Jul 27, 2012 at 20:23
  • multiply it. Wouldn't that imply using the forbidden * operator?
    – luiscubal
    Commented Jul 27, 2012 at 20:59
  • 8
    @luiscubal: No, it won't. This is why I said: "Now all that's left to do is to implement multiplication using bit operations and shifts" Commented Jul 27, 2012 at 21:49
18

Yet another solution. This should handle all ints (including negative ints) except the min value of an int, which would need to be handled as a hard coded exception. This basically does division by subtraction but only using bit operators (shifts, xor, & and complement). For faster speed, it subtracts 3 * (decreasing powers of 2). In c#, it executes around 444 of these DivideBy3 calls per millisecond (2.2 seconds for 1,000,000 divides), so not horrendously slow, but no where near as fast as a simple x/3. By comparison, Coodey's nice solution is about 5 times faster than this one.

public static int DivideBy3(int a) {
    bool negative = a < 0;
    if (negative) a = Negate(a);
    int result;
    int sub = 3 << 29;
    int threes = 1 << 29;
    result = 0;
    while (threes > 0) {
        if (a >= sub) {
            a = Add(a, Negate(sub));
            result = Add(result, threes);
        }
        sub >>= 1;
        threes >>= 1;
    }
    if (negative) result = Negate(result);
    return result;
}
public static int Negate(int a) {
    return Add(~a, 1);
}
public static int Add(int a, int b) {
    int x = 0;
    x = a ^ b;
    while ((a & b) != 0) {
        b = (a & b) << 1;
        a = x;
        x = a ^ b;
    }
    return x;
}

This is c# because that's what I had handy, but differences from c should be minor.

4
  • You only need to try to subtract sub once, because if you could have subtracted it twice then you could have subtracted it the previous iteration when it was twice as big as it is now.
    – Neil
    Commented Jul 28, 2012 at 0:25
  • Does (a >= sub) count as a subtraction?
    – Neil
    Commented Jul 28, 2012 at 0:26
  • @Neil, I think you may be right. The inner while could be replaced with a simple if, saving an unneeded comparison from the second iteration of the loop. Regarding >= being subtraction...I hope not, because that would make doing this quite difficult! I see your point, but I think I would lean on the side that says >= does not count as subtraction. Commented Jul 28, 2012 at 0:34
  • @Neil, I made that change, which cut the time in half (also saved unneeded Negates). Commented Jul 28, 2012 at 0:45
16

It's really quite easy.

if (number == 0) return 0;
if (number == 1) return 0;
if (number == 2) return 0;
if (number == 3) return 1;
if (number == 4) return 1;
if (number == 5) return 1;
if (number == 6) return 2;

(I have of course omitted some of the program for the sake of brevity.) If the programmer gets tired of typing this all out, I'm sure that he or she could write a separate program to generate it for him. I happen to be aware of a certain operator, /, that would simplify his job immensely.

7
  • 8
    You could use a Dictionary<number, number> instead of repeated if statements so you can have O(1) time complexity! Commented Aug 18, 2012 at 3:28
  • @EnesUnal No, the time increases linearly as the number increases, because it has to traverse more and more if statements. Commented Aug 18, 2012 at 21:37
  • Theoritically it does not increase :)
    – totten
    Commented Aug 18, 2012 at 22:01
  • @PeterOlson, EresUnal if I used a switch statement, it'd be O(1) :-) Commented Aug 20, 2012 at 1:51
  • Or you could generate an array, and use dynamic programming. if x/3 = y, then y<<2 + y = x - x%3.
    – lsiebert
    Commented Mar 12, 2015 at 0:01
14

Using counters is a basic solution:

int DivBy3(int num) {
    int result = 0;
    int counter = 0;
    while (1) {
        if (num == counter)       //Modulus 0
            return result;
        counter = abs(~counter);  //++counter

        if (num == counter)       //Modulus 1
            return result;
        counter = abs(~counter);  //++counter

        if (num == counter)       //Modulus 2
            return result;
        counter = abs(~counter);  //++counter

        result = abs(~result);    //++result
    }
}

It is also easy to perform a modulus function, check the comments.

2
  • @Enes Unal: not for small numbers :) This algorithm is very basic.
    – GJ.
    Commented Aug 18, 2012 at 22:10
  • Every primitiveness includes weaknesses :)
    – totten
    Commented Aug 18, 2012 at 22:11
11

This one is the classical division algorithm in base 2:

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

int main()
{
  uint32_t mod3[6] = { 0,1,2,0,1,2 };
  uint32_t x = 1234567; // number to divide, and remainder at the end
  uint32_t y = 0; // result
  int bit = 31; // current bit
  printf("X=%u   X/3=%u\n",x,x/3); // the '/3' is for testing

  while (bit>0)
  {
    printf("BIT=%d  X=%u  Y=%u\n",bit,x,y);
    // decrement bit
    int h = 1; while (1) { bit ^= h; if ( bit&h ) h <<= 1; else break; }
    uint32_t r = x>>bit;  // current remainder in 0..5
    x ^= r<<bit;          // remove R bits from X
    if (r >= 3) y |= 1<<bit; // new output bit
    x |= mod3[r]<<bit;    // new remainder inserted in X
  }
  printf("Y=%u\n",y);
}
10

Write the program in Pascal and use the DIV operator.

Since the question is tagged , you can probably write a function in Pascal and call it from your C program; the method for doing so is system-specific.

But here's an example that works on my Ubuntu system with the Free Pascal fp-compiler package installed. (I'm doing this out of sheer misplaced stubbornness; I make no claim that this is useful.)

divide_by_3.pas :

unit Divide_By_3;
interface
    function div_by_3(n: integer): integer; cdecl; export;
implementation
    function div_by_3(n: integer): integer; cdecl;
    begin
        div_by_3 := n div 3;
    end;
end.

main.c :

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

extern int div_by_3(int n);

int main(void) {
    int n;
    fputs("Enter a number: ", stdout);
    fflush(stdout);
    scanf("%d", &n);
    printf("%d / 3 = %d\n", n, div_by_3(n));
    return 0;
}

To build:

fpc divide_by_3.pas && gcc divide_by_3.o main.c -o main

Sample execution:

$ ./main
Enter a number: 100
100 / 3 = 33
0
8
int div3(int x)
{
  int reminder = abs(x);
  int result = 0;
  while(reminder >= 3)
  {
     result++;

     reminder--;
     reminder--;
     reminder--;
  }
  return result;
}
1
  • 3
    ++ and -- operaors are diferent from + and - operaors! In assembly language there are two instructions ADD and INC that they have not same opcodes. Commented Aug 5, 2012 at 13:50
7

Didn't cross-check if this answer is already published. If the program need to be extended to floating numbers, the numbers can be multiplied by 10*number of precision needed and then the following code can be again applied.

#include <stdio.h>

int main()
{
    int aNumber = 500;
    int gResult = 0;

    int aLoop = 0;

    int i = 0;
    for(i = 0; i < aNumber; i++)
    {
        if(aLoop == 3)
        {
           gResult++;
           aLoop = 0;
        }  
        aLoop++;
    }

    printf("Reulst of %d / 3 = %d", aNumber, gResult);

    return 0;
}
7

This should work for any divisor, not only three. Currently only for unsigned, but extending it to signed should not be that difficult.

#include <stdio.h>

unsigned sub(unsigned two, unsigned one);
unsigned bitdiv(unsigned top, unsigned bot);
unsigned sub(unsigned two, unsigned one)
{
unsigned bor;
bor = one;
do      {
        one = ~two & bor;
        two ^= bor;
        bor = one<<1;
        } while (one);
return two;
}

unsigned bitdiv(unsigned top, unsigned bot)
{
unsigned result, shift;

if (!bot || top < bot) return 0;

for(shift=1;top >= (bot<<=1); shift++) {;}
bot >>= 1;

for (result=0; shift--; bot >>= 1 ) {
        result <<=1;
        if (top >= bot) {
                top = sub(top,bot);
                result |= 1;
                }
        }
return result;
}

int main(void)
{
unsigned arg,val;

for (arg=2; arg < 40; arg++) {
        val = bitdiv(arg,3);
        printf("Arg=%u Val=%u\n", arg, val);
        }
return 0;
}
7

Would it be cheating to use the / operator "behind the scenes" by using eval and string concatenation?

For example, in Javacript, you can do

function div3 (n) {
    var div = String.fromCharCode(47);
    return eval([n, div, 3].join(""));
}
0
6

First that I've come up with.

irb(main):101:0> div3 = -> n { s = '%0' + n.to_s + 's'; (s % '').gsub('   ', ' ').size }
=> #<Proc:0x0000000205ae90@(irb):101 (lambda)>
irb(main):102:0> div3[12]
=> 4
irb(main):103:0> div3[666]
=> 222

EDIT: Sorry, I didn't notice the tag C. But you can use the idea about string formatting, I guess...

6

Using BC Math in PHP:

<?php
    $a = 12345;
    $b = bcdiv($a, 3);   
?>

MySQL (it's an interview from Oracle)

> SELECT 12345 DIV 3;

Pascal:

a:= 12345;
b:= a div 3;

x86-64 assembly language:

mov  r8, 3
xor  rdx, rdx   
mov  rax, 12345
idiv r8
1
  • 2
    Cool story, this is tagged C and has been so since day one. In addition, you completely fail to grasp the point of the question.
    – Lundin
    Commented Jan 23, 2018 at 12:16
5

The following script generates a C program that solves the problem without using the operators * / + - %:

#!/usr/bin/env python3

print('''#include <stdint.h>
#include <stdio.h>
const int32_t div_by_3(const int32_t input)
{
''')

for i in range(-2**31, 2**31):
    print('    if(input == %d) return %d;' % (i, i / 3))


print(r'''
    return 42; // impossible
}
int main()
{
    const int32_t number = 8;
    printf("%d / 3 = %d\n", number, div_by_3(number));
}
''')
5

Using Hacker's Delight Magic number calculator

int divideByThree(int num)
{
  return (fma(num, 1431655766, 0) >> 32);
}

Where fma is a standard library function defined in math.h header.

1
  • How is this not using the - nor the * operator?
    – bitmask
    Commented Jul 27, 2012 at 20:45
5

First:

x/3 = (x/4) / (1-1/4)

Then figure out how to solve x/(1 - y):

x/(1-1/y)
  = x * (1+y) / (1-y^2)
  = x * (1+y) * (1+y^2) / (1-y^4)
  = ...
  = x * (1+y) * (1+y^2) * (1+y^4) * ... * (1+y^(2^i)) / (1-y^(2^(i+i))
  = x * (1+y) * (1+y^2) * (1+y^4) * ... * (1+y^(2^i))

with y = 1/4:

int div3(int x) {
    x <<= 6;    // need more precise
    x += x>>2;  // x = x * (1+(1/2)^2)
    x += x>>4;  // x = x * (1+(1/2)^4)
    x += x>>8;  // x = x * (1+(1/2)^8)
    x += x>>16; // x = x * (1+(1/2)^16)
    return (x+1)>>8; // as (1-(1/2)^32) very near 1,
                     // we plus 1 instead of div (1-(1/2)^32)
}

Although it uses +, but somebody already implements add by bitwise op.

4

How about this approach (c#)?

private int dividedBy3(int n) {
        List<Object> a = new Object[n].ToList();
        List<Object> b = new List<object>();
        while (a.Count > 2) {
            a.RemoveRange(0, 3);
            b.Add(new Object());
        }
        return b.Count;
    }
1
  • This is tagged C and has been so since day one.
    – Lundin
    Commented Jan 23, 2018 at 12:22
4

I think the right answer is:

Why would I not use a basic operator to do a basic operation?

3
  • Because what they want to know is if you know how the processor works internally... using a math operator will in the end perform an operation very similar to the above answer.
    – RaptorX
    Commented Nov 5, 2012 at 18:57
  • Or they wan to know if you can recognize an useless problem.
    – Gregoire
    Commented Nov 20, 2012 at 11:14
  • 1
    @Gregoire I agree, There is aboloultley no need to do such an implementation, Bit in comercial life (Orcale) it is neccessary to avoid fulfilling useless requirments: The correct answer is: "This does not make any sense at all, why loose money for that?")
    – AlexWien
    Commented Dec 14, 2012 at 13:56
4

Solution using fma() library function, works for any positive number:

#include <stdio.h>
#include <math.h>

int main()
{
    int number = 8;//Any +ve no.
    int temp = 3, result = 0;
    while(temp <= number){
        temp = fma(temp, 1, 3); //fma(a, b, c) is a library function and returns (a*b) + c.
        result = fma(result, 1, 1);
    } 
    printf("\n\n%d divided by 3 = %d\n", number, result);
}

See my another answer.

2
  • Nice use of library. Why didn't you directly use result++? Commented Jul 31, 2012 at 3:02
  • then people may say that + has been used.
    – Eight
    Commented Jul 31, 2012 at 3:06
3

Use cblas, included as part of OS X's Accelerate framework.

[02:31:59] [william@relativity ~]$ cat div3.c
#import <stdio.h>
#import <Accelerate/Accelerate.h>

int main() {
    float multiplicand = 123456.0;
    float multiplier = 0.333333;
    printf("%f * %f == ", multiplicand, multiplier);
    cblas_sscal(1, multiplier, &multiplicand, 1);
    printf("%f\n", multiplicand);
}

[02:32:07] [william@relativity ~]$ clang div3.c -framework Accelerate -o div3 && ./div3
123456.000000 * 0.333333 == 41151.957031
2
  • Well, that was just an implementation detail so I could type it as 3.0 / 1.0 instead of 0.333333, but I should play by the rules. Fixed!
    – wjl
    Commented Jul 30, 2012 at 15:48
  • I originally had it as 3.0 / 1.0, which did in my test. By using a higher precision number, they should get a reasonably accurate result. gist.github.com/3401496
    – wjl
    Commented Aug 20, 2012 at 6:00
3

Generally, a solution to this would be:

log(pow(exp(numerator),pow(denominator,-1)))

2

Okay I think we all agree that this isn't a real world problem. So just for fun, here's how to do it with Ada and multithreading:

with Ada.Text_IO;

procedure Divide_By_3 is

   protected type Divisor_Type is
      entry Poke;
      entry Finish;
   private
      entry Release;
      entry Stop_Emptying;
      Emptying : Boolean := False;
   end Divisor_Type;

   protected type Collector_Type is
      entry Poke;
      entry Finish;
   private
      Emptying : Boolean := False;
   end Collector_Type;

   task type Input is
   end Input;
   task type Output is
   end Output;

   protected body Divisor_Type is
      entry Poke when not Emptying and Stop_Emptying'Count = 0 is
      begin
         requeue Release;
      end Poke;
      entry Release when Release'Count >= 3 or Emptying is
         New_Output : access Output;
      begin
         if not Emptying then
            New_Output := new Output;
            Emptying := True;
            requeue Stop_Emptying;
         end if;
      end Release;
      entry Stop_Emptying when Release'Count = 0 is
      begin
         Emptying := False;
      end Stop_Emptying;
      entry Finish when Poke'Count = 0 and Release'Count < 3 is
      begin
         Emptying := True;
         requeue Stop_Emptying;
      end Finish;
   end Divisor_Type;

   protected body Collector_Type is
      entry Poke when Emptying is
      begin
         null;
      end Poke;
      entry Finish when True is
      begin
         Ada.Text_IO.Put_Line (Poke'Count'Img);
         Emptying := True;
      end Finish;
   end Collector_Type;

   Collector : Collector_Type;
   Divisor : Divisor_Type;

   task body Input is
   begin
      Divisor.Poke;
   end Input;

   task body Output is
   begin
      Collector.Poke;
   end Output;

   Cur_Input : access Input;

   -- Input value:
   Number : Integer := 18;
begin
   for I in 1 .. Number loop
      Cur_Input := new Input;
   end loop;
   Divisor.Finish;
   Collector.Finish;
end Divide_By_3;
5
  • This is tagged C and has been so since day one. Your answer is off-topic.
    – Lundin
    Commented Jan 23, 2018 at 12:21
  • Digging up old, closed questions and writing this kind of comment on the answers is as well. It is a waste of time for both of us since you have to write the comment and I see the notification, click on it and need to grasp the context. Neither will it educate me (I cannot even remember writing this) nor will it improve the answer (you are not really thinking I will translate that to C, are you). What are you trying to achieve?
    – flyx
    Commented Jan 23, 2018 at 13:39
  • The problem is that the question isn't closed and has therefore spawned and keeps spawning a flood of off-topic, low quality crap answers. I'm trying to improve the quality of the site by going through the answers, flagging non-answers and down voting off-topic ones. This is btw all community wiki so no rep is affected.
    – Lundin
    Commented Jan 23, 2018 at 13:42
  • Okay, I stand corrected. Wouldn't it be easier to close the question to stop new answers?
    – flyx
    Commented Jan 23, 2018 at 14:00
  • You have my sword.
    – flyx
    Commented Jan 23, 2018 at 14:13

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