0

I was wondering what is faster:

double value = Math.log(a) - Math.log(b);

or

double value = Math.log(a/b);

Could the way I calculate value have an impact on performance (Assume this gets called very often) or does the Java compiler optimize this for me?

Stefan Falk
  • 23,898
  • 50
  • 191
  • 378
  • There is a [related C++ question](also http://stackoverflow.com/questions/2858483/how-can-i-compare-the-performance-of-log-and-fp-division-in-c) – Raedwald Jan 23 '15 at 15:21
  • Carefully consider the context, here; there are many problems in which it is better to work in log-space throughout. If it is a single instance, I'd go for the division. – dwn Jan 23 '15 at 15:22
  • 1
    Why not just test it? – BarrySW19 Jan 23 '15 at 15:32
  • @BarrySW19 Results with micro machines like ours do not really deliver GOOD results when timing CPU speeds. What you should do is to try and find the O(n) of the algorythm. – David Merinos Jan 23 '15 at 15:39
  • 1
    It's hard to talk about impact on performance here, since we're talking about operations that may be going on on the FPU rather than the CPU... It's hard too say – ControlAltDel Jan 23 '15 at 15:41
  • Log is obviously slower than division – harold Jan 23 '15 at 15:48
  • 1
    @DavidMerinos Ah, you want the theoretically correct answer rather than the actually correct answer? – BarrySW19 Jan 23 '15 at 17:16

2 Answers2

3

It's always a good idea to profile and test, but Math.log is much more expensive than either - or /, so Math.log(a/b) (which calls Math.log only once) will, in principle, be faster than Math.log(a) - Math.log(b) (which calls it twice).

Could the way I calculate value have an impact on performance (Assume this gets called very often) or does the Java compiler optimize this for me?

The compiler can't optimize that, no, because the two expressions are not equivalent. (Mathematically, it's true that ln a/b = ln a − ln b, but that's not necessarily true of floating-point numbers, since they are imprecise. And of course, Math.log(-1) - Math.log(-1) is NaN, making it quite different from Math.log(-1 / -1).)

That said . . . you really need to test. Even if this gets called a lot, the difference between the two expressions will probably turn out to be negligible compared to (say) the cost of a nearby println that gets called almost as often. Your program would really have to run this expression an extraordinary number of times per second before you'd expect to observe a difference.

ruakh
  • 175,680
  • 26
  • 273
  • 307
1

I think Math.log(a/b) is faster. Why?

To solve .log(x) the compiler first resolves the value of x which is a/b in this case.

Thus, the steps to solve the log would be:

  1. Solve x
  2. Solve a/b
    1. Solve a
    2. Solve b
  3. Return a/b
  4. Return log(a/b)

On the other hand the substraction of logs would mean to Solve x 2 times (one for a and one for b. Then you'll have to resolve x-y with x and y being .log() operations.

However, Java could optimize all this for you.

David Merinos
  • 1,195
  • 1
  • 14
  • 36