编写一个函数,将数字除以3而不使用/,%和*运算符。 itoa()可用吗?

时间:2010-01-15 11:13:07

标签: algorithm math

我试图自己解决这个问题,但我无法得到任何线索。

请帮我解决这个问题。

18 个答案:

答案 0 :(得分:14)

应该使用itoa()来完成这项任务吗?因为那时您可以使用它转换为基数3字符串,删除最后一个字符,然后恢复到基数10.

答案 1 :(得分:10)

使用数学关系:

1/3 == Sum[1/2^(2n), {n, 1, Infinity}]

我们有

int div3 (int x) {
   int64_t blown_up_x = x;
   for (int power = 1; power < 32; power += 2)
      blown_up_x += ((int64_t)x) << power;
   return (int)(blown_up_x >> 33);
}

如果只能使用32位整数,

int div3 (int x) {
     int two_third = 0, four_third = 0;
     for (int power = 0; power < 31; power += 2) {
        four_third += x >> power;
        two_third += x >> (power + 1);
     }
     return (four_third - two_third) >> 2;
}

使用4/3 - 2/3处理因为x >> 1floor(x/2)而不是round(x/2)

答案 2 :(得分:9)

编辑:哎呀,我误读了标题的问题。也禁止使用乘法运算符。

无论如何,我认为不要删除那些不知道用两个常数的非幂次除法的人的答案。


解决方案是乘以幻数,然后提取最左边的32位:

除以3相当于乘以1431655766然后在C中移位32:

int divideBy3(int n)
{
  return (n * 1431655766) >> 32;
}

请参阅Hacker's Delight Magic number calculator

答案 3 :(得分:9)

x / 3 = e ^(ln(x) - ln(3))

答案 4 :(得分:4)

这是用C ++实现的解决方案:

#include <iostream>

int letUserEnterANumber()
{
    int numberEnteredByUser;
    std::cin >> numberEnteredByUser;
    return numberEnteredByUser;
}

int divideByThree(int x)
{
    std::cout << "What is " << x << " divided by 3?" << std::endl;
    int answer = 0;
    while ( answer + answer + answer != x )
    {
        answer = letUserEnterANumber();
    }
}

- )

答案 5 :(得分:3)

if(number<0){ // Edited after comments
number = -(number);
}
quotient = 0;
while (number-3 >= 0){ //Edited after comments..
number = number-3;
quotient++;
}//after loop exits value in number will give you reminder

编辑:测试并且工作得非常好:(

希望这有帮助。 : - )

答案 6 :(得分:1)

听起来像家庭作业:)。

我想你可以编写一个迭代划分数字的函数。例如。你可以用钢笔和一张纸模拟你的作品来划分数字。或者您可以使用移位运算符和+来确定您的中间结果是否太小/大并且迭代地应用更正。我不打算写下代码......

答案 7 :(得分:1)

您可以使用数字中的属性:如果数字的总和可被3整除,则数字可被3整除。 从itoa()获取各个数字,然后使用switchs函数递归添加和itoa()

希望这有帮助

答案 8 :(得分:1)

这很简单,很容易我只是暗示答案 -

基本布尔逻辑门(和,或者,不是,xor,...)不进行除法。尽管存在这种障碍,CPU仍可以进行划分。你的解决方案是显而易见的:找到一个引用,告诉你如何使用布尔逻辑构建一个除数,并编写一些代码来实现它。

答案 9 :(得分:1)

int divideby3(int n)
{
    int x=0;
    if(n<3) { return 0; }
    while(n>=3)
    {
        n=n-3;
        x++;
    }
    return x;
}

答案 10 :(得分:1)

long divByThree(int x)
{    
  char buf[100];
  itoa(x, buf, 3); 
  buf[ strlen(buf) - 1] = 0; 
  char* tmp; 
  long res = strtol(buf, &tmp, 3);

  return res;
}

答案 11 :(得分:0)

这是一种O(log(n))的实现方式,它没有任何移位,因此它可以处理数字,最大到并包括最大的寄存器大小。

(c样式代码)

long long unsigned Div3 (long long unsigned n)
{
    // base case:
    if (n < 6)
        return (n >= 3);

    long long unsigned division = 0;
    long long unsigned remainder = 0;

    // Used for results for only a single power of 2
    // Initialise for 2^0
    long long unsigned tmp_div = 0;
    long long unsigned tmp_rem = 1;

    for (long long unsigned pow_2 = 1; pow_2 && (pow_2 <= n); pow_2 += pow_2)
    {
        if (n & pow_2)
        {
            division += tmp_div;
            remainder += tmp_rem;
        }
        
        if (tmp_rem == 1)
        {
            tmp_div += tmp_div;
            tmp_rem = 2;
        }
        else
        {
            tmp_div += tmp_div + 1;
            tmp_rem = 1;
        }
    }
    
    return division + Div3(remainder);
}

它使用递归,但请注意,每次迭代时,数字的大小呈指数下降,因此时间复杂度(TC)实际上是:
O(TC) = O(log(n) + log(log(n)) + log(log(log(n))) + ... + z)
z < 6


证明它是O(log(n)):

我们注意到每次递归的次数严格减少(至少减少1):

所以series = [log(log(n))] + [log(log(log(n)))] + [...] + [z])最多有log(log(n))个总和。

series <= log(log(n))*log(log(n))

O(TC) = O(log(n) + log(log(n))*log(log(n)))

现在,我们注意到n足够大: sqrt(x) > log(x) <=> x/sqrt(x) > log(x)

x/log(x) > log(x)
<=>
x > log(x)*log(x)

所以O(x) > O(log(x)*log(x))

现在让x = log(n)

O(log(n)) > O(log(log(n))*log(log(n)))

并给出:
O(TC) = O(log(n) + log(log(n))*log(log(n)))

=>
O(TC) = O(log(n))

[编辑:对格式表示歉意。我不知道为什么有些部分看起来像标题]

答案 12 :(得分:0)

http://bbs.chinaunix.net/forum.php?mod=viewthread&tid=3776384&page=1&extra=#pid22323016

上发布了一个解决方案
int DividedBy3(int A) {
    int p = 0;
    for (int i = 2; i <= 32; i += 2)
        p += A << i;
    return (-p);
}

请说些什么,谢谢:)

答案 13 :(得分:0)

将1/3转换为二进制

所以1/3 = 0.01010101010101010101010101

然后使用shift和sum将这个数字“乘以”加上

答案 14 :(得分:0)

unsigned int  div3(unsigned int m) {
   unsigned long long n = m;
   n += n << 2;
   n += n << 4;
   n += n << 8;
   n += n << 16;
   return (n+m) >> 32;
}

答案 15 :(得分:0)

在某种类似Python的伪代码中,这是怎么回事。它将答案分为整数部分和分数部分。如果你想将它转换为浮点表示,那么我不确定最好的方法。

 x = <a number>  
 total = x
 intpart = 0
 fracpart = 0

 % Find the integer part
 while total >= 3
    total = total - 3
    intpart = intpart + 1

 % Fraction is what remains
 fracpart = total


 print "%d / 3 = %d + %d/3" % (x, intpart, fracpart)

请注意,这不适用于负数。要解决此问题,您需要修改算法:

  total = abs(x)
  is_neg = abs(x) != x

  ....

  if is_neg
      print "%d / 3 = -(%d + %d/3)" % (x, intpart, fracpart)

答案 16 :(得分:0)

用于正整数除法

result = 0
while (result + result + result < input)
 result +=1
return result

答案 17 :(得分:-1)

缓慢而天真,但如果存在确切的除数,它应该有效。允许添加,对吧?

for number from 1 to input
  if number == input+input+input
    return number

将它扩展为小数除数是留给读者的练习。 基本上测试+1和+2我认为...