10

I am self-studying C++ and the book "Programming-Principles and Practices Using C++" by Bjarne Stroustrup. One of the "Try This" asks this:

Implement square() without using the multiplication operator; that is, do the x*x by repeated addition (start a variable result at 0 and add x to it x times). Then run some version of “the first program” using that square().

Basically, I need to make a square(int x) function that will return the square of it without using the multiplication operator. I so far have this:

int square(int x)
{
    int i = 0;
    for(int counter = 0; counter < x; ++counter)
    {
        i = i + x;
    }

return i;
}

But I was wondering if there was a better way to do this. The above function works, but I am highly sure it is not the best way to do it. Any help?

Thomas Ayoub
  • 29,063
  • 15
  • 95
  • 142
  • 1
    You can use shifts and only care about bits that are set in left-hand-side. This is how generic binary multiply works. – Mats Petersson Mar 23 '16 at 03:37
  • http://stackoverflow.com/questions/2776211/how-can-i-multiply-and-divide-using-only-bit-shifting-and-adding You could also use the standard library pow function and square x. – mock_blatt Mar 23 '16 at 03:38
  • 1
    That implementation is clear and is exactly the method the question you referred to asked for you to do it. "Best" is a somewhat ambiguous term. – moreON Mar 23 '16 at 03:40
  • @moreON ok thank you. I am always unsure whenever I try the "Try This" things if I am doing it the most simple and efficient way possible. I'm done! –  Mar 23 '16 at 03:42
  • 3
    You weren't asked to be most efficient! Don't be obsessed with that. Look up premature optimization. – mock_blatt Mar 23 '16 at 03:45
  • Change the i = i + x line to i += x This is just a toy example, you wouldn't use this for real life multiplication so I wouldn't sweat it. Also using the variable 'i' for the loop counter is a bit more idiomatic. – seand Mar 23 '16 at 03:48
  • The best way to do it is: x * x. Note, however, that your square() function does not handle negative numbers correctly. – Zaphod Beeblebrox Mar 23 '16 at 09:28
  • It is certainly not the 'best' way to generate square(x), but that is hardly the point of the exercise! – Clifford Mar 24 '16 at 07:57
  • What's the question exactly? Is there some way to compute a square which is different from both the way you was asked to go and the way you was asked not to go? Yes, there are many. – n. m. could be an AI May 14 '17 at 11:59

7 Answers7

5

Mats Petersson stole the idea out of my head even before I thought to think it.

#include <iostream>

template <typename T>
T square(T x) {
    if(x < 0) x = T(0)-x;
    T sum{0}, s{x};
    while(s) {
        if(s & 1) sum += x;
        x <<= 1;
        s >>= 1;
    }
    return sum;
}

int main() {
    auto sq = square(80);
    std::cout << sq << "\n";
}
Christopher Oicles
  • 3,017
  • 16
  • 11
  • 4
    You probably mean that the Ancient Egyptians stole the idea: https://en.wikipedia.org/wiki/Ancient_Egyptian_multiplication –  Mar 23 '16 at 07:37
  • 4
    On one hand they were a bunch of jerks for stealing my idea, on the other hand their psychic abilities were unimaginably powerful, more than Mats'. Ya gotta respect that. – Christopher Oicles Mar 23 '16 at 07:42
  • 3
    On second thoughts, after fully reading the Wikipedia link, I realize that the Russian Peasants indeed stole your idea, and themselves inspired the Egyptians centuries before. –  Mar 23 '16 at 07:47
  • I declare this set of comments THE WINNER! – lscoughlin Oct 25 '18 at 20:29
1
int square(int x) {
    int result = { 0 };
    int *ptr = &result;
    for (int i = 0; i < x; i++) {
        *ptr = *ptr + x;
    }
    return *ptr;
}

I am reading that book atm. Here is my solution.

icer
  • 11
  • 3
  • Why would you use a pointer at all? You're also reimplementing the ```+=``` operator. ```result += x``` in the loop body would do exactly the same thing. – RL-S Jul 29 '20 at 12:05
0
int square(int x)
{
    int result = 0;
    for (int counter = 0; counter < x; ++counter) result += x;
    return result;
}
0
 int square(int n) 
 { 
        // handle negative input 
        if (n<0) n = -n; 

         // Initialize result 
         int res = n; 

          // Add n to res n-1 times 
          for (int i=1; i<n; i++) 
          res += n; 

      return res; 
 } 
yotke
  • 1,170
  • 2
  • 12
  • 26
0
  //Josef.L
  //Without using multiplication operators.

int square (int a){
     int b = 0; int c =0;
    //I don't need to input value for a, because as a function it already did it for me.
    /*while(b != a){
            b ++;
        c = c + a;}*/
    for(int b = 0; b != a; b++){  //reduce the workload.
        c = c +a;
        //Interesting, for every time b is not equal to a, it will add one to its value:
        //In the same time, when it add one new c = old c + input value will repeat again.
        //Hence when be is equal to a, c which intially is 0 already add to a for a time.
        //Therefore, it is same thing as saying a * a.
    }
    return c;
}

int main(void){
    int a;
    cin >>a;
    cout <<"Square of: "<<a<< " is "<<square(a)<<endl;
return 0;
}

//intricate.

-1

In term of the running time complexity,your implementation is clear and simply enough,its running time is T(n)=Θ(n) for input n elements.Of course you also can use Divide-and-Conquer method,assuming split n elements to n/2:n/2,and finally recursive compute it then sum up two parts,that running time will be like T(n)=2T(n/2)+Θ(n)=Θ(nlgn),we can find its running time complexity become worse than your implementation.

gehan
  • 19
  • 3
  • No, Divide-and-Conquer properly done leads to **T(n)=T(n/2)+Θ(1)**, much better than **Θ(n)**. –  Mar 23 '16 at 07:40
  • @Yves:I think you are wrong,assuming you split the array in the middle size,you can get two sub-tree and its size should be **n/2**, and when you recursively down to leaves,you should sum up every level of recursive tree that will cost **Θ(n)** running time.So, you have two sub-tree and traverse every level of recursive tree to sum up it,and so the totally time should be **T(n)=2T(n/2)+Θ(n)=Θ(nlgn)**. – gehan Mar 23 '16 at 07:57
  • I think I am right, **n/2=n/2** and there is no need for two recursive calls, and there is no **Θ(n)** term. –  Mar 23 '16 at 08:02
  • @YvesDaoust: If your formula **T(n)=T(n/2)+Θ(1)** is right,according to **master theorem** its asymptotic running time should be **Θ(1)**,it is a constant.Does the situation could really happen when use Divide-and-Conquer method? – gehan Mar 23 '16 at 08:04
  • This asymptotic running time is **Θ(log(n))** (the number of times you can halve **n**), review your formulas. –  Mar 23 '16 at 08:08
  • Review my formula,and it satisfy the case 2 of master theorem,so the running time is **Θ(nlg(n))**.And please ask you to review the master theorem and give me a example that its running time is **Θ(log(n))** by use Divide-and-Conquer method to resolve it.Thanks. – gehan Mar 23 '16 at 08:16
  • **T(256) = T(128) + 1 = T(64) + 2 = T(32) + 3 = T(16) + 4 = T(8) + 5 = T(4) + 6 = T(2) + 7 = T(1) + 8**. The example is in front of you. –  Mar 23 '16 at 08:26
  • You just compute half of recursive tree,don't compute the other half recursive tree need to cost time?And please to learn recursive tree carefully,please. – gehan Mar 23 '16 at 08:34
  • Your example is based on your formula is right,but it is wrong actually.And please give me a regular example like a kind of sorting algorithm or what,it should not be a formula that you make it. – gehan Mar 23 '16 at 08:43
  • Have you heard of dichotomic search ? –  Mar 23 '16 at 08:46
  • I know,its running time is Θ(lgn),but your formula for this question is absolutely wrong. – gehan Mar 23 '16 at 08:55
  • your formula is T(n)=T(n/2)+Θ(1),T(n/2) should times 2 and sum up all leaves should be cost Θ(n),so my formula **T(n)=2T(n/2)+Θ(n)=Θ(nlg(n))** should be right and you are wrong.Please read <> carefully. – gehan Mar 23 '16 at 09:18
  • You can't read a recurrence, shame on you. **T(256) = T(128) + 1** and you can continue, reaching **T(256) = T(1) + 8**. The equation reads **Θ(1)**, not **Θ(n)**, and there aren't **n** leaves. –  Mar 23 '16 at 09:46
  • OK,you are so funny.Assume you are right,please note that **assume**.Now, i do not want to split n elements to n/2:n/2,i split them to (n/10):(9n/10),so according to your formula,is should be **T(n)=T(n/10)+Θ(1) ** or **T(n)=T(9n/10)+Θ(1) **, please select one,and **don't** tell me should be **T(n)=T(n/10)+T(9n/10)+Θ(n) **. – gehan Mar 24 '16 at 02:12
  • you are quite right, unbalanced dichotomic search **(1/10, 9/10)** remains **log(n)**, provided the ratio remains constant. In the case of the Egyptian multiplication, this is just impossible, the ratio must be **1/2**. –  Mar 24 '16 at 07:06
-1

You can include <math.h> or <cmath> and use its sqrt() function:

#include <iostream>
#include <math.h>
int square(int);

int main()
{
   int no;
   std::cin >> no;

   std::cout << square(no);
   return 0;
}

int square(int no)
{
   return pow(no, 2);
}
Mr Lister
  • 45,515
  • 15
  • 108
  • 150
JedaiCoder
  • 646
  • 7
  • 12