除以9而不使用除法或乘法运算符

时间:2015-05-31 18:52:40

标签: c algorithm math multiplication integer-division

这个问题我试图解决它,但无法得到任何解决方法。任何指针都会受到赞赏。

常规减法的划分方式不是这里的意图,使用移位算子来完成这一操作的巧妙方法是意图。

7 个答案:

答案 0 :(得分:3)

虽然已经接受了答案,但我会发布我的答案。

<强>更新即可。这通过乘以重复的二进制分数来工作。十进制1/9 = 0.1111111重复出现。在二进制中,即1/1001 = 0.000111000111000111重复出现。

注意二进制乘数是6位的组,小数7是重复的。所以我想在这里做的是将被除数乘以7,将其右移6位,并将其加到运算商中。但是为了保持重要性,我在添加之后进行移位,并在循环结束后移动商q以使其正确对齐。

对于32位int(6位* 6位= 36位),计算循环最多有6次迭代。

#include<stdio.h>

int main(void)
{
    unsigned x, y, q, d;
    int i, err = 0;

    for (x=1; x<100; x++) {             // candidates
        q = 0;                          // quotient
        y = (x << 3) - x;               // y = x * 7

        while(y) {                      // until nothing significant
            q += y;                     // add (effectively) binary 0.000111
            y >>= 6;                    // realign
        }
        q >>= 6;                        // align

        d  = x / 9;                     // the true answer
        if (d != q) {
            printf ("%d / 9 = %d (%d)\n", x, q, d);     // print any errors
            err++;
        }
    }

    printf ("Errors: %d\n", err);
    return 0;
}

不幸的是,对于舍入误差,每个候选者都会失败,因为舍入错误,由于相同的原因,乘以十进制27 * 0.111111 = 2.999999而不是3.所以我现在通过保持4 l.s.来使答案复杂化。舍入的商的位数。结果是它适用于由两个顶部半字节限制的所有int值,一个用于* 7,另一个用于* 16有效值。

#include<stdio.h>

int main(void)
{
    unsigned x, y, q, d;
    int i, err = 0;

    for (x=1; x<0x00FFFFFF; x++) {
        q = 8;                          // quotient with (effectively) 0.5 for rounding
        y = (x << 3) - x;               // y = x * 7
        y <<= 4;                        // y *= 16 for rounding

        while(y) {                      // until nothing significant
            q += y;                     // add (effectively) binary 0.000111
            y >>= 6;                    // realign
        }
        q >>= (4 + 6);                  // the 4 bits significance + recurrence

        d  = x / 9;                     // the true answer
        if (d != q) {
            printf ("%d / 9 = %d (%d)\n", x, q, d);     // print any errors
            err++;
        }
    }

    printf ("Errors: %d\n", err);
    return 0;
}

答案 1 :(得分:2)

请参阅此答案:https://stackoverflow.com/a/11694778/4907651

除了除数是3之外,你正在寻找什么。

编辑:解释

在您不使用add+的情况下寻找解决方案时,我会简单地用*替换/函数。

在这个解释中,我们假设我们除以3

另外,我假设您知道如何将十进制转换为二进制,反之亦然。

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

此方法使用按位运算符:

  • 按位AND:&
  • 按位左移:<<。向左移动二进制值。
  • 按位右移:>>。正确移位二进制值。
  • 按位异或:^

第一个条件(num > 3)是这样的,因为除数是3.在你的情况下,除数是9,所以当你使用它时,条件必须是(num > 9)

假设我们要分割的数字是6。

在二进制中,6表示为000110

现在,我们输入while (num > 3)循环。第一个语句将sum(初始化为0)添加到num >> 2

num >> 2的作用:

  最初的二进制数

00000000 00000110

     按位移后

00000000 00000001 i.e. 1 in decimal

添加sum

num >> 21

由于我们知道num >> 2等于1,我们将其添加到num & 3

  最初的二进制数

00000000 00000110

     

3 in binary:00000000 00000011

对于表达式a & b的结果中的每个位位置,如果两个操作数都包含1,则该位为1,否则为0

  

num & 3的结果:00000000 00000010 i.e. 2 in decimal

num等于num = (num >> 2) + (num & 3) = 1 + 2

3

现在,由于num等于3,我们输入if (num==3)循环。

然后我们将sum加1,并返回值。 sum的此值为商。

正如所料,返回的值是2。

希望这不是一个可怕的解释。

答案 2 :(得分:1)

创建一个循环,每一步你应该减去N-9 ..然后(N-9)-9 ...直到N<9 OR N=0并且你计算每个减法步骤例如:36/9 36-9=27 cmpt (1) 27-9=18 cmpt(2) 18-9=9 cmpt(3) 9-9=0 cmpt (4)

所以36/9= 4

答案 3 :(得分:1)

这是一个受Hacker's Delight启发的解决方案,它真正只使用了一些位移:

def divu9(n):
    q = n - (n >> 3)
    q = q + (q >> 6)
    q = q + (q>>12) + (q>>24); q = q >> 3
    r = n - (((q << 2) << 1) + q)
    return q + ((r + 7) >> 4)
    #return q + (r > 8)

答案 4 :(得分:0)

这个http://en.wikipedia.org/wiki/Ancient_Egyptian_multiplication算法只能在log(n)时间内使用减法和二进制移位来实现。但是,据我所知,最先进的硬件已经使用了这个,甚至更好的算法。因此,我认为你不能做任何事情(假设性能是你的目标),除非你能以某种方式完全避免分裂或改变你的用例,这样你可以除以2的幂,因为这些有一些技巧例。

答案 5 :(得分:0)

如果您需要除以正数,可以使用以下函数:

unsigned int divideBy9(unsigned int num) 
{
    unsigned int result = 0;
    while (num >= 9)
    {
        result += 1;
        num -= 9;
    }
    return result;
}

如果是负数,您可以使用类似的方法。

希望这有帮助!

答案 6 :(得分:0)

如果您不允许乘法/除法,则可以使用加法/减法。除以数字表示除数包含被除数的次数。您可以使用此作为回报:您可以从原始值中减去该数字多少次?

divisor = 85;
dividend = 9;
remaining = divisor;
result = 0;
while (remaining >= dividend)
{
    remaining -= dividend;
    result++;
}
std::cout << divisor << " / " << dividend << " = " << result;