29

I had an interesting interview yesterday where the interviewer asked me a classic question: How can we multiply two numbers in Java without using the * operator. Honestly, I don't know if it's the stress that comes with interviews, but I wasn't able to come up with any solution.

After the interview, I went home and breezed through SO for answers. So far, here are the ones I have found:

First Method: Using a For loop

// Using For loop
public static int multiplierLoop(int a, int b) {
    int resultat = 0;
    for (int i = 0; i < a; i++) {
        resultat += b;
    }

    return resultat;
}

Second Method: Using Recursion

// using Recursion
public static int multiplier(int a, int b) {

    if ((a == 0) || (b == 0))
        return 0;
    else
        return (a + multiplier(a, b - 1));

}

Third Method: Using Log10

**// Using Math.Log10
public static double multiplierLog(int a, int b) {
    return Math.pow(10, (Math.log10(a) + Math.log10(b)));
}**

So now I have two questions for you:

  1. Is there still another method I'm missing?
  2. Does the fact that I wasn't able to come up with the answer proves that my logical reasoning isn't strong enough to come up with solutions and that I'm not "cut out" to be a programmer? Cause let's be honest, the question didn't seem that difficult and I'm pretty sure most programmers would easily and quickly find an answer.
Lii
  • 11,553
  • 8
  • 64
  • 88
Jesse James
  • 1,203
  • 5
  • 22
  • 39
  • 2
    [Bitwise multiply](https://stackoverflow.com/questions/4895173/bitwise-multiply-and-add-in-java) – Oleksandr Pyrohov Jun 01 '18 at 08:49
  • 1
    2. If you like programming and you're willing to put in the work, then you're cut out for it. The same goes for technical interviewing. Only you can decide if you feel it's worth the effort – Simon Jun 01 '18 at 09:42
  • 5
    I wonder what an interviewer would say if you used a web client to poll Google / WolframAlpha. Or, if you created a new file, then appended _X_ bytes to it _Y_ times, then polled the OS for its file size. Or, the same, except with thread sleeps, then measured the result by subtracting starting and ending time stamps... – Nat Jun 01 '18 at 12:13
  • 1
    You might enjoy this: https://codegolf.stackexchange.com/questions/40257/multiply-two-numbers-without-using-any-numbers – N. Virgo Jun 01 '18 at 14:14
  • None of the 3 method listed here actually work for all ranges of a and b, even if the effects of overflow are ignored. Before embarking on reinventing the wheel, ensure you have a small flotilla of unit test cases ready. – StuartLC Jun 01 '18 at 14:21
  • In the third method you can use any king of log (logn, log2... etc) :) – dhalfageme Jun 18 '20 at 19:00
  • you don't need to check `a==0` in the recursion example. – hazzik Jun 04 '21 at 04:32

9 Answers9

29

I don't know whether that has to be a strictly "programming question". But in Maths:

x * y = x / (1 / y) #divide by inverse

So:

Method 1:

public static double multiplier(double a, double b) {

    // return a / (1 / b);

    // the above may be too rough
    // Java doesn't know that "(a / (b / 0)) == 0"
    // a special case for zero should probably be added:

    return 0 == b ? 0 : a / (1 / b);
}

Method 2 (a more "programming/API" solution):

Use big decimal, big integer:

new BigDecimal("3").multiply(new BigDecimal("9"))

There are probably a few more ways.

ernest_k
  • 44,416
  • 5
  • 53
  • 99
  • If you used method 1, I would ask you if any rounding error was possible, just to watch you suffer. :) (Well, also I'm curious, but it sounds like a huge pain to prove if it is NOT possible--and if it is possible, then this is not a correct way to multiply.) – user3067860 Jun 01 '18 at 13:52
  • @user3067860 of course, there are rounding errors possible. That's why this trick doesn't work with integers at all. And for `double`, try for example with `a = 3.0, b = 75.0`... – Holger Jun 01 '18 at 15:30
18

There is a method called [Russian Peasant Multiplication][1]. Demonstrate this with the help of a shift operator,

public static int multiply(int n, int m)
{ 
    int ans = 0, count = 0;
    while (m > 0)
    {
        if (m % 2 == 1)             
            ans += n << count;
        count++;
        m /= 2;
    }
     
    return ans;
}

The idea is to double the first number and halve the second number repeatedly till the second number doesn’t become 1. In the process, whenever the second number become odd, we add the first number to result (result is initialized as 0) One other implementation is,

static int russianPeasant(int n, int m) {
    int ans = 0;

    while (m > 0) {
        if ((m & 1) != 0)
            ans = ans + n;

        n = n << 1;
        m = m >> 1;
    }
    return ans;
}

refer :

Glorfindel
  • 21,988
  • 13
  • 81
  • 109
prime
  • 14,464
  • 14
  • 99
  • 131
12

Others have hit on question 1 sufficiently that I'm not going to rehash it here, but I did want to hit on question 2 a little, because it seems (to me) the more interesting one.

So, when someone is asking you this type of question, they are less concerned with what your code looks like, and more concerned with how you are thinking. In the real world, you won't ever actually have to write multiplication without the * operator; every programming language known to man (with the exception of Brainfuck, I guess) has multiplication implemented, almost always with the * operator. The point is, sometimes you are working with code, and for whatever reason (maybe due to library bloat, due to configuration errors, due to package incompatibility, etc), you won't be able to use a library you are used to. The idea is to see how you function in those situations.

The question isn't whether or not you are "cut out" to be a programmer; skills like these can be learned. A trick I use personally is to think about what, exactly, is the expected result for the question they're asking? In this particular example, as I (and I presume you as well) learned in grade 4 in elementary school, multiplication is repeated addition. Therefore, I would implement it (and have in the past; I've had this same question in a few interviews) with a for loop doing repeated addition.

The thing is, if you don't realize that multiplication is repeated addition (or whatever other question you're being asked to answer), then you'll just be screwed. Which is why I'm not a huge fan of these types of questions, because a lot of them boil down to trivia that you either know or don't know, rather than testing your true skills as a programmer (the skills mentioned above regarding libraries etc can be tested much better in other ways).

Ertai87
  • 1,156
  • 1
  • 15
  • 26
  • 1
    I was right there with you until the last paragraph. If you don't realize that multiplication is repeated addition, then either you haven't taken grade-school math, or you haven't really internalized the concept of breaking a problem down to its smaller components. If it's the latter, that's actually a bit of a flag. In fact, it's probably the _only_ useful bit of data I would hope to take from a question like this, as an interviewer. (I don't think it's a great question.) And actually, having that realization should probably pretty quickly get you to realize the loop implementation, at least. – yshavit Jun 01 '18 at 16:35
  • That said, a good interviewer should help you get past any one bit you struggle on, so that they can evaluate you on the other components. If I were asking this question and they got stuck, I'd prompt them with "well, what does it really mean to multiply two numbers? What does '4 times 3' actually mean?" in an effort to get them to think/remember "oh, it's 3 4s added together, it's just repeated addition." If they didn't get the loop from that, I'd prompt them with "how would you do a repeated action in Java?" If they don't get _that_, they're probably in trouble, tbh. – yshavit Jun 01 '18 at 16:38
  • @yshavit All that is true, however, it's possible that you didn't learn that addition is repeated multiplication in school (I don't know how else you would learn multiplication, but maybe you just didn't learn it that way). Getting a job in your adult life really ought not to depend on whether your 4th grade math teacher taught you something the way the interviewer, 20+ years later, expected it to be taught. – Ertai87 Jun 01 '18 at 17:31
  • I think that's a flag, though. Maybe there's a good reason for it; but it's a basic enough bit of data (as you alluded to) that if someone didn't know it, I'd want to know why. Is this person's math proficiency low enough that they won't know what p99 latency means? Or do they have trouble breaking down obvious things? It's not a veto point, but it's a something to dig into. – yshavit Jun 01 '18 at 18:31
6

TL;DR - Inform the interviewer that re-inventing the wheel is a bad idea

Rather than entertain the interviewer's Code Golf question, I would have answered the interview question differently:

Brilliant engineers at Intel, AMD, ARM and other microprocessor manufacturers have agonized for decades as how to multiply 32 bit integers together in the fewest possible cycles, and in fact, are even able to produce the correct, full 64 bit result of multiplication of 32 bit integers without overflow.

(e.g. without pre-casting a or b to long, a multiplication of 2 ints such as 123456728 * 23456789 overflows into a negative number)

In this respect, high level languages have only one job to do with integer multiplications like this, viz, to get the job done by the processor with as little fluff as possible.

Any amount of Code Golf to replicate such multiplication in software IMO is insanity.

There's undoubtedly many hacks which could simulate multiplication, although many will only work on limited ranges of values a and b (in fact, none of the 3 methods listed by the OP perform bug-free for all values of a and b, even if we disregard the overflow problem). And all will be (orders of magnitude) slower than an IMUL instruction.

For example, if either a or b is a positive power of 2, then bit shifting the other variable to the left by log can be done.

if (b == 2)
   return a << 1;
if (b == 4)
   return a << 2;
... 

But this would be really tedious.

In the unlikely event of the * operator really disappearing overnight from the Java language spec, next best, I would be to use existing libraries which contain multiplication functions, e.g. BigInteger.multiply(), for the same reasons - many years of critical thinking by minds brighter than mine has gone into producing, and testing, such libraries.

BigInteger.multiply would obviously be reliable to 64 bits and beyond, although casting the result back to a 32 bit int would again invite overflow problems.

The problem with playing operator * Code Golf

There's inherent problems with all 3 of the solutions cited in the OP's question:

  • Method A (loop) won't work if the first number a is negative.

 for (int i = 0; i < a; i++) {
      resultat += b;
  }

Will return 0 for any negative value of a, because the loop continuation condition is never met

  • In Method B, you'll run out of stack for large values of b in method 2, unless you refactor the code to allow for Tail Call Optimisation

multiplier(100, 1000000)

"main" java.lang.StackOverflowError

  • And in Method 3, you'll get rounding errors with log10 (not to mention the obvious problems with attempting to take a log of any number <= 0). e.g.

multiplier(2389, 123123);

returns 294140846, but the actual answer is 294140847 (the last digits 9 x 3 mean the product must end in 7)

Even the answer using two consecutive double precision division operators is prone to rounding issues when re-casting the double result back to an integer:

static double multiply(double a, double b) {
    return 0 == (int)b 
       ? 0.0 
       : a / (1 / b);
}

e.g. for a value (int)multiply(1, 93) returns 92, because multiply returns 92.99999.... which is truncated with the cast back to a 32 bit integer.

And of course, we don't need to mention that many of these algorithms are O(N) or worse, so the performance will be abysmal.

StuartLC
  • 104,537
  • 17
  • 209
  • 285
2

For completeness:

Math.multiplyExact(int,int):

Returns the product of the arguments, throwing an exception if the result overflows an int.

if throwing on overflow is acceptable.

Hulk
  • 6,399
  • 1
  • 30
  • 52
2

If you don't have integer values, you can take advantage of other mathematical properties to get the product of 2 numbers. Someone has already mentioned log10, so here's a bit more obscure one:

public double multiply(double x, double y) {
    Vector3d vx = new Vector3d(x, 0, 0);
    Vector3d vy = new Vector3d(0, y, 0);
    Vector3d result = new Vector3d().cross(vx, vy);
    return result.length();
}
DavidW
  • 1,413
  • 10
  • 17
2

One solution is to use bit wise operations. That's a bit similar to an answer presented before, but eliminating division also. We can have something like this. I'll use C, because I don't know Java that well.

uint16_t multiply( uint16_t a, uint16_t b ) {
  uint16_t i = 0;
  uint16_t result = 0;

  for (i = 0; i < 16; i++) {
    if ( a & (1<<i) ) {
      result += b << i;
    }
  }
  return result;
}
lkrv
  • 21
  • 3
1

The questions interviewers ask reflect their values. Many programmers prize their own puzzle-solving skills and mathematical acumen, and they think those skills make the best programmers.

They are wrong. The best programmers work on the most important thing rather than the most interesting bit; make simple, boring technical choices; write clearly; think about users; and steer away from stupid detours. I wish I had these skills and tendencies!

If you can do several of those things and also crank out working code, many programming teams need you. You might be a superstar.


But what should you do in an interview when you're stumped?

Ask clarifying questions. ("What kind of numbers?" "What kind of programming language is this that doesn't have multiplication?" And without being rude: "Why am I doing this?") If, as you suspect, the question is just a dumb puzzle with no bearing on reality, these questions will not produce useful answers. But common sense and a desire to get at "the problem behind the problem" are important engineering virtues.

The best you can do in a bad interview is demonstrate your strengths. Recognizing them is up to your interviewer; if they don't, that's their loss. Don't be discouraged. There are other companies.

Jason Orendorff
  • 42,793
  • 6
  • 62
  • 96
0

Use BigInteger.multiply or BigDecimal.multiply as appropriate.

emory
  • 10,725
  • 2
  • 30
  • 58