这个问题我试图解决它,但无法得到任何解决方法。任何指针都会受到赞赏。
常规减法的划分方式不是这里的意图,使用移位算子来完成这一操作的巧妙方法是意图。
答案 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;
}
此方法使用按位运算符:
&
。 <<
。向左移动二进制值。 >>
。正确移位二进制值。^
第一个条件(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 >> 2
为1
。
由于我们知道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;