关于C#:不使用*,/,+, – ,%运算符将数字除以3

Divide a number by 3 without using *, /, +, -, % operators

在不使用*/+-%运算符的情况下,如何将数字除以3?

号码可以是有符号的或无符号的。


这是一个执行所需操作的简单函数。但它需要+运算符,因此您只需使用位运算符添加值:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 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;
}

正如吉姆所说,这是可行的,因为:

  • n = 4 * a + b
  • n / 3 = a + (a + b) / 3
  • 因此,sum += an = a + b和迭代

  • a == 0 (n < 4)时,sum += floor(n / 3);即1、if n == 3, else 0


愚蠢的条件需要一个愚蠢的解决方案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#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;
}

如果还需要小数部分,只需声明resultdouble,并加上fmod(number,divisor)的结果。

解释其工作原理

  • fwrite写入number字节(上面例子中的数字是123456)。
  • rewind将文件指针重置到文件前面。
  • fread从文件中最多读取number条长度为divisor的"记录",并返回其读取的元素数。
  • 如果写入30个字节,然后以3为单位读取文件,则得到10个"单位"。30/3=10


    1
    log(pow(exp(number),0.33333333333333333333)) /* :-) */


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    #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
    "
    , r.quot);

        return 0;
    }


    您可以使用(依赖平台)内联程序集,例如,用于x86:(也适用于负数)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    #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
    "
    , dividend, divisor, quotient, remainder);
      return 0;
    }


    使用ITOA转换为基3字符串。放下最后一个Trit,然后转换回Base 10。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    // 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
    }


    (注:请参阅下面的编辑2以获得更好的版本!)

    这并不像听起来那么复杂,因为您说过"不使用[..]+[..]操作符"。如果要禁止同时使用+字符,请参见下面的内容。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    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;
    }

    那么就说div_by(100,3)100除以3

    编辑:您还可以继续替换++操作符:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    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)
    }

    编辑2:速度稍快的版本,不使用包含+-*/%字符的任何运算符。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    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;
    }

    我们使用add函数的第一个参数,因为我们不能在不使用*字符的情况下表示指针的类型,除非在函数参数列表中,其中语法type[]type* const相同。

    fwiw,您可以使用类似的技巧轻松实现乘法函数,使用andreyt提出的0x55555556技巧:

    1
    2
    3
    4
    5
    int mul(int const x, int const y) {
      return sizeof(struct {
        char const ignore[y];
      }[x]);
    }


    它是可能的setun很容易在计算机上。

    西安市的两个整数除以3,1右移位的城市广场。

    在我不确定它是否是可能的严格实施的一个C编译器的协调通过一个这样的平台,但。我们可能会有两个伸展的游戏规则(一位样解释,"至少8位"AA"capable控股(至少从两个integers + 127 128"。


    由于它的从Oracle,如何查找表的前一部calculated回答。:D


    我的解决方案是:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    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);
    }

    首先,注意

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

    现在,剩下的很简单!

    1
    2
    3
    4
    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 + ...

    现在我们要做的就是把这些位移值加起来!哎呀!但是我们不能添加,因此我们必须使用位运算符编写一个添加函数!如果您熟悉位智能运算符,我的解决方案应该看起来相当简单…不过,万一你没有,我最后会举个例子。

    另一件事要注意的是,我第一次左移30!这是为了确保分数不会四舍五入。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    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!

    你小时候学的只是简单的加法!

    1
    2
    3
    4
    5
    111
     1011
    +0110
    -----
    10001

    此实现失败,因为我们无法添加公式的所有项:

    1
    2
    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

    假设EDOCX1的reslut(39)=x,然后是x <= floor(f(a, i)) < a / 3。当a = 3k时,我们得到了错误的答案。


    要将32位数字除以3,可以将其乘以0x55555556,然后取64位结果的上32位。

    现在剩下要做的就是用位操作和移位实现乘法…


    而另一个解决方案。我们应该采取行动(包括负全ints ints)"除非我个int值,这将需要两个手腕硬编码作为一个例外。这是basically分市subtraction但只使用位操作人员(shifts,异或,&;鸭补)。因为它的速度快,subtracts 3×(缓变的权力(2)。在# C,它在executes 444个divideby3要求每millisecond(2.2秒为1000000 divides),所以不horrendously慢,但没有在近AA房作为一个简单的X / 3。城市的对比,很好的解决方案coodey冰约5小时禁食,这一个。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    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;
    }

    这是# C,因为那就是仇恨得心应手,但差异应该是从C小调。


    它的真的很长很容易。

    1
    2
    3
    4
    5
    6
    7
    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;

    (当然有一些omitted报计划部的缘故brevity)。如果计划得到了这部全typlng疲倦了,我生气,他或她可以写一个程序,它的两个Generate他。发生在两个感知某运营商/,那会immensely简化他的工作。


    使用的计数器是一个基本的解决方案:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    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
        }
    }

    它也很容易perform a模两种功能,检查的评论。


    这是一个经典的分割算法在基地2:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    #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
    "
    ,x,x/3); // the '/3' is for testing

      while (bit>0)
      {
        printf("BIT=%d  X=%u  Y=%u
    "
    ,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
    "
    ,y);
    }

    用pascal编写程序,并使用DIV操作符。

    因为这个问题被标记为C,所以您可以用Pascal编写一个函数并从C程序中调用它;这样做的方法是特定于系统的。

    但这里有一个在我的Ubuntu系统上运行的例子,安装了免费的pascal fp-compiler包。(我这样做完全是出于错位的固执;我没有声称这是有用的。)

    divide_by_3.pas

    1
    2
    3
    4
    5
    6
    7
    8
    9
    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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    #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, div_by_3(n));
        return 0;
    }

    建造:

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

    样本执行:

    1
    2
    3
    $ ./main
    Enter a number: 100
    100 / 3 = 33

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    int div3(int x)
    {
      int reminder = abs(x);
      int result = 0;
      while(reminder >= 3)
      {
         result++;

         reminder--;
         reminder--;
         reminder--;
      }
      return result;
    }


    这应该对任何因子的工作,不只是三。目前只有在unsigned展,但它不应该是两个签名,难。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    #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
    "
    , arg, val);
            }
    return 0;
    }

    没有交叉检查,如果这个答案已经发表的冰。如果程序需要两个扩展浮数,数可以倍增10×号城市大学精密需要下面的代码,然后可以应用了。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    #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;
    }

    使用PHP数学:在公元前

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

    (它的MySQL的访谈从Oracle)

    1
    > SELECT 12345 DIV 3;

    Pascal:

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

    x86 64装配语言:

    1
    2
    3
    4
    mov  r8, 3
    xor  rdx, rdx  
    mov  rax, 12345
    idiv r8


    它是将两个使用欺骗的/operator"背后的"舞台"的城市用eval和字符串concatenation吗?

    例如,在javacript,你能做的

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

    第一,我在用VC来的IP。

    1
    2
    3
    4
    5
    6
    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

    编辑:对不起,我没有注意到你的C。但你不可以使用字符串格式编排的想法是,我想……


    下面的脚本generates C程序,用solves问题没有所谓的运营商* / + - %

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    #!/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
    ", number, div_by_3(number));
    }
    '
    '')

    使用黑客的喜悦幻数计算器

    1
    2
    3
    4
    int divideByThree(int num)
    {
      return (fma(num, 1431655766, 0) >> 32);
    }

    其中,fma是在math.h头中定义的标准库函数。


    我认为正确的答案是:

    为什么不使用基本运算符执行基本操作?


    这种方法(c)怎么样?

    1
    2
    3
    4
    5
    6
    7
    8
    9
    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;
        }


    溶液(FMA)图书馆的使用功能,工程的任何积极的编号:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    #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("

    %d divided by 3 = %d
    "
    , number, result);
    }

    看我的另一个答案。


    使用cblas部分包括AS,OS X的accelerate框架。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    [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
    "
    , multiplicand);
    }

    [02:32:07] [william@relativity ~]$ clang div3.c -framework Accelerate -o div3 && ./div3
    123456.000000 * 0.333333 == 41151.957031


    第一:

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

    然后找出如何求解x/(1-y):

    1
    2
    3
    4
    5
    6
    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))

    y=1/4:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    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)
    }

    虽然它使用了+,但已经有人实现了按位运算加法。


    很有趣,没有人用一般的划分来回答:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    /* For the given integer find the position of MSB */
    int find_msb_loc(unsigned int n)
    {
        if (n == 0)
            return 0;

        int loc = sizeof(n)  * 8 - 1;
        while (!(n & (1 << loc)))
            loc--;
        return loc;
    }


    /* Assume both a and b to be positive, return a/b */
    int divide_bitwise(const unsigned int a, const unsigned int b)
    {
        int int_size = sizeof(unsigned int) * 8;
        int b_msb_loc = find_msb_loc(b);

        int d = 0; // dividend
        int r = 0; // reminder
        int t_a = a;
        int t_a_msb_loc = find_msb_loc(t_a);
        int t_b = b << (t_a_msb_loc - b_msb_loc);

        int i;
        for(i = t_a_msb_loc; i >= b_msb_loc; i--)  {
            if (t_a > t_b) {
                d = (d << 1) | 0x1;
                t_a -= t_b; // Not a bitwise operatiion
                t_b = t_b >> 1;
             }
            else if (t_a == t_b) {
                d = (d << 1) | 0x1;
                t_a = 0;
            }
            else { // t_a < t_b
                d = d << 1;
                t_b = t_b >> 1;
            }
        }

        r = t_a;
        printf("==> %d %d
    "
    , d, r);
        return d;
    }

    其中一个答案中已经给出了按位加法,因此跳过它。


    所有答案可能都不是面试官喜欢听到的:

    我的回答是:

    "I would never do that, who will me pay for such silly things. Nobody
    will have an advantage on that, its not faster, its only silly.
    Prozessor designers have to know that, but this must then work for all numbers, not only for division by 3"


    好吧,我想我们都同意这不是现实世界的问题。为了好玩,下面介绍如何使用ADA和多线程:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    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;


    其中inputValue是要除以3的数字

    1
    2
    3
    4
    SELECT AVG(NUM)
      FROM (SELECT InputValue NUM from sys.dual
             UNION ALL SELECT 0 from sys.dual
             UNION ALL SELECT 0 from sys.dual) divby3


    如果你提醒自己标准的学校除法,并用二进制进行除法,你会发现在3的情况下,你只需要除法和减法一组有限的值(在这种情况下从0到5)。这些可以用switch语句处理,以去掉算术运算符。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    static unsigned lamediv3(unsigned n)
    {
      unsigned result = 0, remainder = 0, mask = 0x80000000;

      // Go through all bits of n from MSB to LSB.
      for (int i = 0; i < 32; i++, mask >>= 1)
      {
        result <<= 1;
        // Shift in the next bit of n into remainder.
        remainder = remainder << 1 | !!(n & mask);

        // Divide remainder by 3, update result and remainer.
        // If remainder is less than 3, it remains intact.
        switch (remainder)
        {
        case 3:
          result |= 1;
          remainder = 0;
          break;

        case 4:
          result |= 1;
          remainder = 1;
          break;

        case 5:
          result |= 1;
          remainder = 2;
          break;
        }
      }

      return result;
    }

    #include <cstdio>

    int main()
    {
      // Verify for all possible values of a 32-bit unsigned integer.
      unsigned i = 0;

      do
      {
        unsigned d = lamediv3(i);

        if (i / 3 != d)
        {
          printf("failed for %u: %u != %u
    "
    , i, d, i / 3);
          return 1;
        }
      }
      while (++i != 0);
    }


    一般来说,解决这一问题的办法是:

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


    为什么我们不应用大学里学过的定义呢?结果可能效率低下,但很清楚,因为乘法只是一个递归减法,减法是一个加法,那么加法可以通过递归XOR/和逻辑端口组合执行。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    #include <stdio.h>

    int add(int a, int b){
       int rc;
       int carry;
       rc = a ^ b;
       carry = (a & b) << 1;
       if (rc & carry)
          return add(rc, carry);
       else
          return rc ^ carry;
    }

    int sub(int a, int b){
       return add(a, add(~b, 1));
    }

    int div( int D, int Q )
    {
    /* lets do only positive and then
     * add the sign at the end
     * inversion needs to be performed only for +Q/-D or -Q/+D
     */

       int result=0;
       int sign=0;
       if( D < 0 ) {
          D=sub(0,D);
          if( Q<0 )
             Q=sub(0,Q);
          else
             sign=1;
       } else {
          if( Q<0 ) {
             Q=sub(0,Q);
             sign=1;
          }
       }
       while(D>=Q) {
          D = sub( D, Q );
          result++;
       }
    /*
    * Apply sign
    */

       if( sign )
          result = sub(0,result);
       return result;
    }

    int main( int argc, char ** argv )
    {
        printf("2 plus 3=%d
    "
    , add(2,3) );
        printf("22 div 3=%d
    "
    , div(22,3) );
        printf("-22 div 3=%d
    "
    , div(-22,3) );
        printf("-22 div -3=%d
    "
    , div(-22,-3) );
        printf("22 div 03=%d
    "
    , div(22,-3) );
        return 0;
    }

    就像有人说的…首先让这个工作。注意,算法应该适用于负Q…


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    #include <stdio.h>

    typedef struct { char a,b,c; } Triple;

    unsigned long div3(Triple *v, char *r) {
      if ((long)v <= 2)  
        return (unsigned long)r;
      return div3(&v[-1], &r[1]);
    }

    int main() {
      unsigned long v = 21;
      int r = div3((Triple*)v, 0);
      printf("%ld / 3 = %d
    "
    , v, r);
      return 0;
    }

    这将起作用…

    1
    smegma$ curl http://www.wolframalpha.com/input/?i=14+divided+by+3 2>/dev/null | gawk 'match($0, /link to /input/\?i=([0-9.+-]+)/, ary) { print substr( $0, ary[1,"start"], ary[1,"length"] )}' 4.6666666666666666666666666666666666666666666666666666

    用你的数字代替14和3。


    我将使用这个代码来划分所有正数和非浮点数。基本上,您需要将除数位左对齐以匹配被除数位。对于被除数的每个部分(除数的大小),您要检查以确保被除数的部分是否大于除数,然后您要左移然后在第一个注册器中移动。这个概念最初创建于2004年(我相信斯坦福德),这里是一个使用这个概念的C版本。注:(我修改了一下)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    int divide(int a, int b)
    {
        int c = 0, r = 32, i = 32, p = a + 1;
        unsigned long int d = 0x80000000;

        while ((b & d) == 0)
        {
            d >>= 1;
            r--;
        }

        while (p > a)
        {
            c <<= 1;
            p = (b >> i--) & ((1 << r) - 1);
            if (p >= a)
                c |= 1;
        }
        return c; //p is remainder (for modulus)
    }

    示例用法:

    1
    int n = divide( 3, 6); //outputs 2

    似乎没有人提到用二进制表示的3的除法标准——偶数和等于奇数的和(类似于十进制的11)。如果一个数可以被3整除,那么有一些使用这种技巧的解决方案需要检查。

    我想这可能是迈克尔·伯尔编辑提到的复制品。


    3在11座2的冰。

    所以只要做长除法(像在中学2)在11座城市。它是更容易吗?即使在基地10比2座。

    对每个位的起始位置和最重要的:

    决定如果低于11字头的冰。

    如果它是输出0。

    如果它是不输出1,然后代用品字头的钻头的适当的变更。有只有三例:

    1
    2
    3
     11xxx ->    xxx    (ie 3 - 3 = 0)
    100xxx ->   1xxx    (ie 4 - 3 = 1)
    101xxx ->  10xxx    (ie 5 - 3 = 2)

    所有其他prefixes是unreachable。

    重复,直到最低位的位置,你会做的。


    1
    2
    3
    4
    5
    #!/bin/ruby

    def div_by_3(i)
      i.div 3        # always return int http://www.ruby-doc.org/core-1.9.3/Numeric.html#method-i-div
    end


    如果我们考虑__div__/冰槽

    1
    2
    3
    4
    def divBy3(n):
        return n.__div__(3)

    print divBy3(9), 'or', 9//3

    采用Linux shell脚本:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    #include <stdio.h>
    int main()
    {
        int number = 30;
        char command[25];
        snprintf(command, 25,"echo $((%d %c 3))", number, 47);
        system( command );
        return 0;
    }

    看我的另一个答案。


    你可以考虑使用一个类似于图/树的结构来解决这个问题。基本上,生成的顶点数量等于要除以3的数字。然后将每个未配对的顶点与其他两个顶点配对。

    粗伪代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    function divide(int num)
        while(num!=0)
            Add a new vertice to vertiexList.
            num--
        quotient = 0
        for each in vertexList(lets call this vertex A)
            if vertexList not empty
                Add an edge between A and another vertex(say B)
            else
                your Remainder is 1 and Quotient is quotient
            if vertexList not empty
                Add an edge between A and another vertex(say C)
            else
                your remainder is 2 and Quotient is quotient
            quotient++
            remove A, B, C from vertexList
        Remainder is 0 and Quotient is quotient

    这显然是可以优化的,复杂程度取决于你的数字有多大,但是如果你能做到+和-,它就可以工作了。它只不过是清凉点而已。


    它是在与basically,Python字符串比较,和一个状态机。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    def divide_by_3(input):
      to_do = {}
      enque_index = 0
      zero_to_9 = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
      leave_over = 0
      for left_over in (0, 1, 2):
        for digit in zero_to_9:
          # left_over, digit => enque, leave_over
          to_do[(left_over, digit)] = (zero_to_9[enque_index], leave_over)
          if leave_over == 0:
            leave_over = 1
          elif leave_over == 1:
            leave_over = 2
          elif leave_over == 2 and enque_index != 9:
            leave_over = 0
            enque_index = (1, 2, 3, 4, 5, 6, 7, 8, 9)[enque_index]
      answer_q = []
      left_over = 0
      digits = list(str(input))
      if digits[0] =="-":
        answer_q.append("-")
      digits = digits[1:]
      for digit in digits:
        enque, left_over = to_do[(left_over, int(digit))]
        if enque or len(answer_q):
          answer_q.append(enque)
      answer = 0
      if len(answer_q):
        answer = int("".join([str(a) for a in answer_q]))
      return answer

    bc好"的奥运会。

    1
    2
    3
    $ num=1337; printf"scale=5;${num}\x2F3;
    "
    | bc
    445.66666

    这是我小时候祖父教我的方法。它需要+和/运算符,但它使计算变得容易。

    把各个数字加在一起,看是不是3的倍数。

    但这种方法适用于12以上的数字。

    例子:36,

    3+6=9,是3的倍数。

    42,

    4+2=6,是3的倍数。