3

I want to implement multiplication of two integer numbers without using multiplication operator, in .NET

public uint MultiplyNumbers(uint x, uint y)
{

}

Any idea!

Jacob
  • 77,566
  • 24
  • 149
  • 228
Pingpong
  • 7,681
  • 21
  • 83
  • 209

7 Answers7

26

I'm assuming this is homework... otherwise there's no sane reason you'd want to do it. Therefore I'll just give hints...

  • If performance isn't terribly important, consider that x * 3 = x + x + x... think about using a loop.

  • If performance is important but you know that one of the numbers will be small, loop on the smaller number.

  • If performance is important and both numbers could be large, you'll need to think about bit-twiddling. Remember that x * 2 is x << 1, and go from there.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 1
    I am disappointed with the hint, which leads to an exponential-time algorithm, while `mult(a,b) = a == 0 ? 0 : mult(a>>1, b<<1) + ((a & 1) == 1 ? b : 0)` is no more complex, but linear-time. I’ve written it here as a recursive function, but of course it can be converted to a loop easily. – Timwi May 03 '11 at 22:41
  • @Timwi, thanks, what is the definition of mult method? – Pingpong May 04 '11 at 00:26
  • 1
    @Timwi: Your hint is what the third bullet is about. I dispute the idea that it's "no more complex" than a loop... my aim was to give a *simple* answer first, but hint at a more performant approach if the OP wants to go further. I also fail to see how the loop would be exponential time, unless you assume that addition is linear itself. I would assume constant time for addition, leading to a linear "add in a loop" complexity, and a logarithmic complexity for the bitshifting version. – Jon Skeet May 04 '11 at 06:13
  • @Jon: When we talk about the complexity of algorithms we express it in terms of the number of bits in the input, not the magnitude of the number represented by it. – Timwi May 04 '11 at 19:44
  • @Pingpong: That grey block in my comment *is* the definition. – Timwi May 04 '11 at 19:45
  • @Timwi: You may do... I don't tend to. If I'm expressing the complexity of computing Fib(n) for some value of n, I talk about the value of n, not the number of bits in it. Note that here the maximum number of bits we have to deal with is already fixed at 32... I think it's rather easier to understand in terms of `n` rather than `log n`, myself. – Jon Skeet May 04 '11 at 21:03
  • @Jon: Firstly, the maximum magnitude of `n` is also fixed at 2³²−1, so that argument is bogus. But more importantly, if you want to use algorithmic complexity differently from established practice, you should state explicitly that this is what you’re doing. And to be consistent, you should also claim that Bubble Sort is O(log n) instead of O(n²). – Timwi May 04 '11 at 22:17
  • @Timwi: I don't view it as established practice to use the number of bits for all complexities. For *some* it makes sense, although I'd always state that explicitly. In this case I'd say it makes sense both ways... so long as we're explicit. Going back to the original question, are you still convinced that your bitshifting version is "no more complex" than repeated addition? Just as easy to understand for everyone? – Jon Skeet May 05 '11 at 05:30
  • @Timwi: Just to lower the temperature of the conversation a little, I absolutely agree that the number of bits in the input is the most appropriate measure in many cases. Just not all... and I think it's worth being explicit when it's not 100% obvious. I'm happy to update my answer to include the complexity of both the naive addition and the bitshifting version, expressing that complexity both in terms of the magnitude of the inputs and the bitwise size of them. I still believe that the "repeated add" is simpler to understand than the bitshifting version. – Jon Skeet May 05 '11 at 06:01
  • @Timwi: Since any modern machine operates on chunks of 32/64 bits at a time, it is customary in "Systems" space, to express complexity of operations as if one operation on such a chunk (representing the value of a number n) is O(1) instead of O(log n). – hawk May 05 '11 at 08:26
  • @Jon: Of course the bit-shifting version is harder for humans to understand. I grant you that. But that’s just because humans don’t think like computers :) — Don’t worry about editing your answer, I’m just nitpicking anyway. Maybe I should just shut up. — @hawk: I know that. What I said applies even with that. – Timwi May 06 '11 at 01:03
12

It goes against the spirit of the assignment, but I'd do it for kicks...

Create your own class, overload the + operator to do multiplication.

Create your homework project; add your first project as a reference. Write your code to be

return new SuperInt(x) + SuperInt(y);

Everyone else is going to some variation of shifting bits or addition. Half of the kids are going to post the exact code returned by a Google search anyway. At least this way, you'll be unique.

The assignment itself is really just an exercise in lateral thinking. Any sane person would use the * operator when working in .Net.

EDIT: If you really want to be a class clown - overload the * operator and implement it with bitwise operations and addition.

Additional Answer #1 (if you are willing to change your method signature...) What about this?

static void Main(string[] args)
{
    Console.WriteLine(string.Format("{0} * {1} = {2}", 5, 6, MultiplyNumbers(5, 6)));
    Console.WriteLine(string.Format("{0} * {1} = {2}", -5, 6, MultiplyNumbers(-5, 6)));
    Console.WriteLine(string.Format("{0} * {1} = {2}", -5, -6, MultiplyNumbers(-5, -6)));
    Console.WriteLine(string.Format("{0} * {1} = {2}", 5, 1, MultiplyNumbers(5, 1)));
    Console.Read();
}


static double MultiplyNumbers(double x, double y)
{
    return x / (1 / y);
}

Outputs:

5 * 6 = 30
-5 * 6 = -30
-5 * -6 = 30
5 * 1 = 5

One straight-forward line of code.

But still, if you take this approach, be prepared to argue a bit. It does multiply integers; by implicitly converting them to doubles in the call. Your question didn't say you could use only integers, just that it had to multiply two integers without using '*'.

EDIT: Since you say you can't change the signature of MultiplyNumbers - you can accomplish it without doing that:

static uint MultiplyNumbers(uint x, uint y)
{
    return MultiplyDouble(x, y);
}

static uint MultiplyDouble(double x, double y)
{
    return Convert.ToUInt32(x / (1 / y));
}

Additional Answer #2 This is my favorite approach yet.

Take the values, send them to Google, parse the result.

static uint MultiplyNumbers(uint x, uint y)
{
    System.Net.WebClient myClient = new System.Net.WebClient();
    string sData = myClient.DownloadString(string.Format("http://www.google.com/search?q={0}*{1}&btnG=Search",x,y));

    string ans = x.ToString() + " * " + y.ToString() + " = ";
    int iBegin = sData.IndexOf(ans,50) + ans.Length ;
    int iEnd = sData.IndexOf('<',iBegin);

    return Convert.ToUInt32(sData.Substring(iBegin, iEnd - iBegin).Trim());
}
Rob P.
  • 14,921
  • 14
  • 73
  • 109
12

Look, ma, no * operator!

using System;
using System.Reflection.Emit;

static class Program
{
    delegate uint UintOpDelegate(uint a, uint b);

    static void Main()
    {
        var method = new DynamicMethod("Multiply",
            typeof(uint), new Type[] { typeof(uint), typeof(uint) });
        var gen = method.GetILGenerator();
        gen.Emit(OpCodes.Ldarg_0);
        gen.Emit(OpCodes.Ldarg_1);
        gen.Emit(OpCodes.Mul);
        gen.Emit(OpCodes.Ret);

        var del = (UintOpDelegate)method.CreateDelegate(typeof(UintOpDelegate));

        var product = del(2, 3); //product is now 6!
    }
}

Even better:

using System;
using System.Runtime.InteropServices;

delegate uint BinaryOp(uint a, uint b);

static class Program
{
    [DllImport("kernel32.dll", SetLastError = true)]
    static extern bool VirtualProtect(
        IntPtr address, IntPtr size, uint protect, out uint oldProtect);

    static void Main()
    {
        var bytes = IntPtr.Size == sizeof(int) //32-bit? It's slower BTW
            ? Convert.FromBase64String("i0QkBA+vRCQIww==")
            : Convert.FromBase64String("D6/Ki8HD");
        var handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
        try
        {
            uint old;
            VirtualProtect(handle.AddrOfPinnedObject(),
                (IntPtr)bytes.Length, 0x40, out old);
            var action = (BinaryOp)Marshal.GetDelegateForFunctionPointer(
                handle.AddrOfPinnedObject(), typeof(BinaryOp));
            var temp = action(3, 2); //6!
        }
        finally { handle.Free(); }
    }
}
user541686
  • 205,094
  • 128
  • 528
  • 886
4

You can simply loop for x times, adding y to a running total on each iteration.

razlebe
  • 7,134
  • 6
  • 42
  • 57
4

Repeated addition would work. Add 'x' to a running total 'y' times.

var total = 0;

for(int i = 0; i < y; i++)
{
    total += x;
}
Michael Arnell
  • 1,008
  • 1
  • 9
  • 16
4

You can use bitwise operators to do multiplication.

x<<1

is x*2 and so on.

You will still have to do some addition.

   result=0;
   while(b != 0)               
   {
      if (b&01)                
        {
          result=result+a;     
        }
      a<<=1;                   
      b>>=1;                   
   }

From: Multiplication of two integers using bitwise operators

Community
  • 1
  • 1
manojlds
  • 290,304
  • 63
  • 469
  • 417
  • thanks, I got your idea. but you just copied from that site! plagiarism? Thanks! – Pingpong May 03 '11 at 17:15
  • 3
    Copied what? I have included the source of the code. See the link. And even if I hadn't included the link, it would just be bad ethics and not plagiarism. It is just a code snippet. – manojlds May 03 '11 at 17:16
1
public uint MultiplyNumbers(uint x, uint y) {
    if (x == 0 || y == 0) return 0;

    uint answer = x;

    for (uint i = 1; i < y; ++i) 
        answer += x;

    return answer;
}
trydis
  • 3,905
  • 1
  • 26
  • 31