133

Here's a silly fun question:

Let's say we have to perform a simple operation where we need half of the value of a variable. There are typically two ways of doing this:

y = x / 2.0;
// or...
y = x * 0.5;

Assuming we're using the standard operators provided with the language, which one has better performance?

I'm guessing multiplication is typically better so I try to stick to that when I code, but I would like to confirm this.

Although personally I'm interested in the answer for Python 2.4-2.5, feel free to also post an answer for other languages! And if you'd like, feel free to post other fancier ways (like using bitwise shift operators) as well.

edmundito
  • 1,552
  • 2
  • 10
  • 10
  • 5
    Did you run a benchmark? It's only about a dozen lines of code. What did you learn from running a benchmark? [Hint: doing that would have been quicker than posting the question here.] – S.Lott Oct 22 '08 at 16:06
  • The timeit command in IPython is one line – endolith Dec 02 '09 at 04:15
  • 4
    Great question, which has generated some quite interesting answers / discussions. Thanks :) – stealthcopter Feb 01 '11 at 21:00
  • See http://stackoverflow.com/questions/20263050/is-0-25-faster-than-4-in-vb-net/20263750#20263750 for a VB.NET discussion of essentially the same question, with a benchmark. – Kevin Whitefoot Nov 28 '13 at 11:05
  • 34
    Even if he had learned the answer by benchmarking it it is still a useful question and has generated some interesting and useful answers. Also I wish people would stick to the point and refrain from writing answers and comments to answers offering irrelevant advice on whether or not it is worth making the optimization in question. Why not assume that the OP is asking the question as written instead of assuming that he or she 'really' wants advice on a larger scale rewrite. – Kevin Whitefoot Nov 28 '13 at 11:08
  • 1
    Division is much slower, than multiplication. But some smart compliers / VMs transform division into multiplication, so your tests will have the same results (both tests test multiplication). – Ivan Kuckir Jul 04 '14 at 13:44
  • 6
    A bit off topic, but I just want to say how much I agree with @KevinWhitefoot. There is nothing as frustrating as reading from sermonizers rather than strai technical answers to technical questions. Thanks Kevin for your comment! – Jean-François Mar 05 '15 at 04:46

25 Answers25

86

Python:

time python -c 'for i in xrange(int(1e8)): t=12341234234.234 / 2.0'
real    0m26.676s
user    0m25.154s
sys     0m0.076s

time python -c 'for i in xrange(int(1e8)): t=12341234234.234 * 0.5'
real    0m17.932s
user    0m16.481s
sys     0m0.048s

multiplication is 33% faster

Lua:

time lua -e 'for i=1,1e8 do t=12341234234.234 / 2.0 end'
real    0m7.956s
user    0m7.332s
sys     0m0.032s

time lua -e 'for i=1,1e8 do t=12341234234.234 * 0.5 end'
real    0m7.997s
user    0m7.516s
sys     0m0.036s

=> no real difference

LuaJIT:

time luajit -O -e 'for i=1,1e8 do t=12341234234.234 / 2.0 end'
real    0m1.921s
user    0m1.668s
sys     0m0.004s

time luajit -O -e 'for i=1,1e8 do t=12341234234.234 * 0.5 end'
real    0m1.843s
user    0m1.676s
sys     0m0.000s

=>it's only 5% faster

conclusions: in Python it's faster to multiply than to divide, but as you get closer to the CPU using more advanced VMs or JITs, the advantage disappears. It's quite possible that a future Python VM would make it irrelevant

Javier
  • 60,510
  • 8
  • 78
  • 126
  • Thanks for the tip on using the time command for benchmarking! – edmundito Oct 22 '08 at 17:11
  • 2
    Your conclusion is wrong. It gets more relevant as the JIT/VM gets better. The division gets slower compared to the lower overhead of the VM. Remember that compilers generally cannot optimize floating point much in order to guarantee precision. – rasmus Sep 14 '12 at 07:22
  • 9
    @rasmus: As the JIT gets better, it becomes more likely to use a CPU multiplication instruction even though you asked for division. – Ben Voigt Jul 26 '13 at 14:04
73

Always use whatever is the clearest. Anything else you do is trying to outsmart the compiler. If the compiler is at all intelligent, it will do the best to optimize the result, but nothing can make the next guy not hate you for your crappy bitshifting solution (I love bit manipulation by the way, it's fun. But fun != readable)

Premature optimization is the root of all evil. Always remember the three rules of optimization!

  1. Don't optimize.
  2. If you are an expert, see rule #1
  3. If you are an expert and can justify the need, then use the following procedure:

    • Code it unoptimized
    • determine how fast is "Fast enough"--Note which user requirement/story requires that metric.
    • Write a speed test
    • Test existing code--If it's fast enough, you're done.
    • Recode it optimized
    • Test optimized code. IF it doesn't meet the metric, throw it away and keep the original.
    • If it meets the test, keep the original code in as comments

Also, doing things like removing inner loops when they aren't required or choosing a linked list over an array for an insertion sort are not optimizations, just programming.

Bill K
  • 62,186
  • 18
  • 105
  • 157
  • 8
    that's not the full Knuth quote; see http://en.wikipedia.org/wiki/Optimization_(computer_science)#When_to_optimize – Jason S Mar 18 '09 at 00:15
  • No, there are about 40 different quotes on the subject from as many different sources. I kind of piece a few together. – Bill K Mar 18 '09 at 17:08
  • Your last sentence makes it unclear when to apply rules #1 and #2, leaving us back where we started: We need to decide which optimizations are worthwhile and which ones are not. Pretending the answer is obvious is not an answer. – Matt Jan 19 '16 at 10:15
  • 2
    It's really that confusing to you? Always apply rule 1 and 2 unless you actually don't meet client specifications and are very familiar with the entire system including the language and caching characteristics of the CPU. At that point, ONLY follow the procedure in 3, don't just think "Hey, if I cache this variable locally instead of calling a getter, things will probably be quicker. First prove that it's not fast enough then test each optimization separately and throw out the ones that don't help. Document heavily all along the way. – Bill K Jan 19 '16 at 19:12
49

I think this is getting so nitpicky that you would be better off doing whatever makes the code more readable. Unless you perform the operations thousands, if not millions, of times, I doubt anyone will ever notice the difference.

If you really have to make the choice, benchmarking is the only way to go. Find what function(s) are giving you problems, then find out where in the function the problems occur, and fix those sections. However, I still doubt that a single mathematical operation (even one repeated many, many times) would be a cause of any bottleneck.

Thomas Owens
  • 114,398
  • 98
  • 311
  • 431
  • 1
    When I used to make radar processors, a single operation did make a difference. But we were hand-optimizing the machine code to achieve real-time performance. For everything else, I vote for simple and obvious. – S.Lott Oct 22 '08 at 16:54
  • I guess for some things, you might care about a single operation. But I would expect that in 99% of the applications out there, it doesn't matter. – Thomas Owens Oct 22 '08 at 17:05
  • 27
    Especially since the OP was looking for an answer in Python. I doubt anything which needs that amount of efficiency would be written in Python. – Ed S. Oct 23 '08 at 00:57
  • 4
    A division is probably the most expensive operation in a triangle intersection routine, which is the basis for most raytracers. If you store the reciprocal and multiply instead of dividing, you will experience many times speedup. – solinent Jun 16 '10 at 17:08
  • @solinent -- yes a speedup but I doubt "many times" -- floating-point division and multiplication shouldn't be different by more than about 4:1, unless the processor in question is really really optimized for multiplication and not division. – Jason S Feb 07 '17 at 17:43
  • @JasonS a 4:1 sounds like a pretty significative improvement to me. "what? You just made the game go from 15 fps to 60 fps? That is insignificant. You are fired!!!" – user1593842 Mar 03 '18 at 16:14
  • I agree with that, I just don't think 4:1 is "many times". Yes it's worth doing, but let's be accurate. – Jason S Mar 06 '18 at 17:52
41

Multiplication is faster, division is more accurate. You'll lose some precision if your number isn't a power of 2:

y = x / 3.0;
y = x * 0.333333;  // how many 3's should there be, and how will the compiler round?

Even if you let the compiler figure out the inverted constant to perfect precision, the answer can still be different.

x = 100.0;
x / 3.0 == x * (1.0/3.0)  // is false in the test I just performed

The speed issue is only likely to matter in C/C++ or JIT languages, and even then only if the operation is in a loop at a bottleneck.

Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
  • Division is accurate if you're dividing by whole numbers. – plinth Oct 22 '08 at 16:23
  • 7
    Floating-point division with denominator > numerator must introduce meaningless values in the low-order bits; division usually reduces accuracy. – S.Lott Oct 22 '08 at 16:56
  • 8
    @S.Lott: No, that's not true. All IEEE-754-compliant floating point implementations must round the results of every operation perfectly (i.e. to the nearest floating point number) with respect to the current rounding mode. Multiplying by the reciprocal is always going to introduce more error, at least because one more rounding must happen. – Electro Apr 21 '13 at 10:06
  • 1
    I know this answer is over 8 years old, but it's misleading; you can perform division without significant loss of precision: `y = x * (1.0/3.0);` and the compiler will generally compute 1/3 at compile-time. Yes, 1/3 is not perfectly representable in IEEE-754, but when you're performing floating-point arithmetic you're losing precision *anyway*, whether you're doing multiplication or division, because the low-order bits are rounded. If you know your computation is that sensitive to rounding error, you should also know how to best deal with the issue. – Jason S Feb 05 '17 at 18:54
  • 3
    @JasonS I just left a program running overnight, starting at 1.0 and counting up by 1 ULP; I compared the result of multiplying by `(1.0/3.0)` with dividing by `3.0`. I got up to 1.0000036666774155, and in that space 7.3% of the results were different. I presume they were only different by 1 bit, but since IEEE arithmetic is guaranteed to round to the closest correct result I stand by my statement that division is more accurate. Whether the difference is significant is up to you. – Mark Ransom Feb 07 '17 at 02:11
  • @JasonS for an example that fails, try 1.0009765625. – Mark Ransom Feb 07 '17 at 02:15
26

If you want to optimize your code but still be clear, try this:

y = x * (1.0 / 2.0);

The compiler should be able to do the divide at compile-time, so you get a multiply at run-time. I would expect the precision to be the same as in the y = x / 2.0 case.

Where this may matter a LOT is in embedded processors where floating-point emulation is required to compute floating-point arithmetic.

Jason S
  • 184,598
  • 164
  • 608
  • 970
  • 13
    Suit yourself (and whoever -1'd this) -- it is standard practice in the embedded world and software engineers in that field find it clear. – Jason S Dec 02 '10 at 19:04
  • 4
    +1 for being the only one here realizing that compilers cannot optimize floating point operations however they want. They can't even change the order of operands in a multiplication in order to guarantee precision (unless it uses a relaxed mode). – rasmus Sep 14 '12 at 07:18
  • 1
    OMG, there are at least 6 programmers thinking that elementary math is unclear. AFAIK, IEEE 754 multiplication is commutative (but non-associative). – maaartinus Sep 27 '14 at 18:58
  • 13
    Perhaps you're missing the point. It has nothing to do with algebraic correctness. In an ideal world you should just be able to divide by two: `y = x / 2.0;`, but in the real world, you may have to cajole the compiler into performing a less-expensive multiply. Maybe it's less clear why `y = x * (1.0 / 2.0);` is better, and it would be clearer to state `y = x * 0.5;` instead. But change the `2.0` to a `7.0` and I'd much rather see `y = x * (1.0 / 7.0);` than `y = x * 0.142857142857;`. – Jason S Sep 28 '14 at 18:15
  • 3
    This really makes it clear why it is more legible (and precise) to use your method. – Juan Martinez Jan 13 '15 at 11:58
  • @rasmus: Ironically, this specific example is one case where the compiler *can* legally do this optimization without violating strict FP semantics, and real compilers like GCC and clang do. `2.0` is a power of 2, so its reciprocal `0.5` is exactly representable as a float or double. See [Why do compilers not coerce "n / 2.0" into "n \* 0.5" if it's faster?](//stackoverflow.com/q/75188241) for an example (it does if you enable optimization, as an answer shows.) For divisors with reciprocals which can't be exactly represented, you have to do it manually or use `-ffast-math` if you want speed. – Peter Cordes Jan 20 '23 at 19:13
21

Just going to add something for the "other languages" option.
C: Since this is just an academic exercise that really makes no difference, I thought I would contribute something different.

I compiled to assembly with no optimizations and looked at the result.
The code:

int main() {

    volatile int a;
    volatile int b;

    asm("## 5/2\n");
    a = 5;
    a = a / 2;

    asm("## 5*0.5");
    b = 5;
    b = b * 0.5;

    asm("## done");

    return a + b;

}

compiled with gcc tdiv.c -O1 -o tdiv.s -S

the division by 2:

movl    $5, -4(%ebp)
movl    -4(%ebp), %eax
movl    %eax, %edx
shrl    $31, %edx
addl    %edx, %eax
sarl    %eax
movl    %eax, -4(%ebp)

and the multiplication by 0.5:

movl    $5, -8(%ebp)
movl    -8(%ebp), %eax
pushl   %eax
fildl   (%esp)
leal    4(%esp), %esp
fmuls   LC0
fnstcw  -10(%ebp)
movzwl  -10(%ebp), %eax
orw $3072, %ax
movw    %ax, -12(%ebp)
fldcw   -12(%ebp)
fistpl  -16(%ebp)
fldcw   -10(%ebp)
movl    -16(%ebp), %eax
movl    %eax, -8(%ebp)

However, when I changed those ints to doubles (which is what python would probably do), I got this:

division:

flds    LC0
fstl    -8(%ebp)
fldl    -8(%ebp)
flds    LC1
fmul    %st, %st(1)
fxch    %st(1)
fstpl   -8(%ebp)
fxch    %st(1)

multiplication:

fstpl   -16(%ebp)
fldl    -16(%ebp)
fmulp   %st, %st(1)
fstpl   -16(%ebp)

I haven't benchmarked any of this code, but just by examining the code you can see that using integers, division by 2 is shorter than multiplication by 2. Using doubles, multiplication is shorter because the compiler uses the processor's floating point opcodes, which probably run faster (but actually I don't know) than not using them for the same operation. So ultimately this answer has shown that the performance of multiplaction by 0.5 vs. division by 2 depends on the implementation of the language and the platform it runs on. Ultimately the difference is negligible and is something you should virtually never ever worry about, except in terms of readability.

As a side note, you can see that in my program main() returns a + b. When I take the volatile keyword away, you'll never guess what the assembly looks like (excluding the program setup):

## 5/2

## 5*0.5
## done

movl    $5, %eax
leave
ret

it did both the division, multiplication, AND addition in a single instruction! Clearly you don't have to worry about this if the optimizer is any kind of respectable.

Sorry for the overly long answer.

Carson Myers
  • 37,678
  • 39
  • 126
  • 176
  • 1
    It's not a "single instruction". It just got constant folded. – kvanbere Jul 13 '13 at 04:35
  • 5
    @kvanberendonck Of course it's a single instruction. Count them: `movl $5, %eax` The name of the optimization isn't important or even relevant. You just wanted to be condescending on a four year old answer. – Carson Myers Jul 14 '13 at 22:45
  • 2
    The nature of the optimization is still important to understand, because it's context-sensitive: It only applies if you're adding/multiplying/dividing/etc. compile-time constants, where the compiler can just do all of the math in advance and move the final answer into a register at runtime. Division is a lot slower than multiplication in the general case (runtime divisors), but I suppose multiplying by reciprocals only helps if you'd otherwise divide by the same denominator more than once anyway. You probably know all that, but newer programmers might need it spelled out, so...just in case. – Mike S Nov 24 '13 at 23:58
  • Why only `-O1`? Also, a better way to get asm to look at is to write a function that takes args and returns a value. You don't need or want a `main` if you're just looking at the asm. (You specifically want to avoid `main` with GCC because it has an implicit `__attribute__((cold))` for main.) But yes, multiplying an integer by `0.5` is total garbage, especially with legacy x87 where truncation from FP to integer is very inconvenient, having to change the rounding mode. – Peter Cordes Jan 20 '23 at 19:20
11

Firstly, unless you are working in C or ASSEMBLY, you're probably in a higher level language where memory stalls and general call overheads will absolutely dwarf the difference between multiply and divide to the point of irrelevance. So, just pick what reads better in that case.

If you're talking from a very high level it won't be measurably slower for anything you're likely to use it for. You'll see in other answers, people need to do a million multiply/divides just to measure some sub-millisecond difference between the two.

If you're still curious, from a low level optimisation point of view:

Divide tends to have a significantly longer pipeline than multiply. This means it takes longer to get the result, but if you can keep the processor busy with non-dependent tasks, then it doesn't end up costing you any more than a multiply.

How long the pipeline difference is is completely hardware dependant. Last hardware I used was something like 9 cycles for a FPU multiply and 50 cycles for a FPU divide. Sounds a lot, but then you'd lose 1000 cycles for a memory miss, so that can put things in perspective.

An analogy is putting a pie in a microwave while you watch a TV show. The total time it took you away from the TV show is how long it was to put it in the microwave, and take it out of the microwave. The rest of your time you still watched the TV show. So if the pie took 10 minutes to cook instead of 1 minute, it didn't actually use up any more of your tv watching time.

In practice, if you're going to get to the level of caring about the difference between Multiply and Divide, you need to understand pipelines, cache, branch stalls, out-of-order prediction, and pipeline dependencies. If this doesn't sound like where you were intending to go with this question, then the correct answer is to ignore the difference between the two.

Many (many) years ago it was absolutely critical to avoid divides and always use multiplies, but back then memory hits were less relevant, and divides were much worse. These days I rate readability higher, but if there's no readability difference, I think its a good habit to opt for multiplies.

James Podesta
  • 266
  • 2
  • 7
8

Write whichever is more clearly states your intent.

After your program works, figure out what's slow, and make that faster.

Don't do it the other way around.

Jay Bazuzi
  • 45,157
  • 15
  • 111
  • 168
6

Actually there is a good reason that as a general rule of thumb multiplication will be faster than division. Floating point division in hardware is done either with shift and conditional subtract algorithms ("long division" with binary numbers) or - more likely these days - with iterations like Goldschmidt's algorithm. Shift and subtract needs at least one cycle per bit of precision (the iterations are nearly impossible to parallelize as are the shift-and-add of multiplication), and iterative algorithms do at least one multiplication per iteration. In either case, it's highly likely that the division will take more cycles. Of course this does not account for quirks in compilers, data movement, or precision. By and large, though, if you are coding an inner loop in a time sensitive part of a program, writing 0.5 * x or 1.0/2.0 * x rather than x / 2.0 is a reasonable thing to do. The pedantry of "code what's clearest" is absolutely true, but all three of these are so close in readability that the pedantry is in this case just pedantic.

Gene
  • 46,253
  • 4
  • 58
  • 96
6

Do whatever you need. Think of your reader first, do not worry about performance until you are sure you have a performance problem.

Let compiler do the performance for you.

buti-oxa
  • 11,261
  • 5
  • 35
  • 44
4

If you are working with integers or non floating point types don't forget your bitshifting operators: << >>

    int y = 10;
    y = y >> 1;
    Console.WriteLine("value halved: " + y);
    y = y << 1;
    Console.WriteLine("now value doubled: " + y);
sbeskur
  • 2,260
  • 23
  • 23
  • 7
    this optimization is automatically performed behind the scenes in any modern compiler. – Dustin Getz Oct 22 '08 at 16:11
  • Has anyone tested if checking (using bit ops) if an operand(?) has a shiftable version to use that instead? function mul ( a, b ){ if ( b is 2 ) return a << 1; if ( b is 4 ) return a << 2; // ... etc return a*b; } My guess is that the IF is so expensive it would be less efficient. – Christopher Lightfoot Oct 22 '08 at 16:14
  • That didn't print anywhere close to what I imagined; Nevermind. – Christopher Lightfoot Oct 22 '08 at 16:14
  • For const operations a normal compiler should do the work; but here we're using python so I'm not sure if its smart enough to know? (It should be). – Christopher Lightfoot Oct 22 '08 at 16:15
  • Good shortcut, except that it's not immediately clear what's really happening. Most programmers don't even recognize the bitshift operators. – Blazemonger Dec 08 '11 at 18:42
  • since this actually happens with -O1 and higher (mul/div gets replaced by bit shifts and additions/subtractions), coding it by hand is 1. evil, 2. premature. –  Jan 31 '14 at 18:16
3

Multiplication is usually faster - certainly never slower. However, if it is not speed critical, write whichever is clearest.

Dan Hewett
  • 2,200
  • 1
  • 14
  • 18
2

I have always learned that multiplication is more efficient.

Toon Krijthe
  • 52,876
  • 38
  • 145
  • 202
  • "efficient" is the wrong word. It is true that most processors multiply faster than they divide. However, with modern pipelined archtectures your program may see no difference. As many others are saying, you are really *way* better off just doing what reads best to a human. – T.E.D. Oct 22 '08 at 17:06
2

Floating-point division is (generally) especially slow, so while floating-point multiplication is also relatively slow, it's probably faster than floating-point division.

But I'm more inclined to answer "it doesn't really matter", unless profiling has shown that division is a bit bottleneck vs. multiplication. I'm guessing, though, that the choice of multiplication vs. division isn't going to have a big performance impact in your application.

mipadi
  • 398,885
  • 90
  • 523
  • 479
2

This becomes more of a question when you are programming in assembly or perhaps C. I figure that with most modern languages that optimization such as this is being done for me.

Seamus
  • 1,215
  • 8
  • 6
2

Be wary of "guessing multiplication is typically better so I try to stick to that when I code,"

In context of this specific question, better here means "faster". Which is not very useful.

Thinking about speed can be a serious mistake. There are profound error implications in the specific algebraic form of the calculation.

See Floating Point arithmetic with error analysis. See Basic Issues in Floating Point Arithmetic and Error Analysis.

While some floating-point values are exact, most floating point values are an approximation; they are some ideal value plus some error. Every operation applies to the ideal value and the error value.

The biggest problems come from trying to manipulate two nearly-equal numbers. The right-most bits (the error bits) come to dominate the results.

>>> for i in range(7):
...     a=1/(10.0**i)
...     b=(1/10.0)**i
...     print i, a, b, a-b
... 
0 1.0 1.0 0.0
1 0.1 0.1 0.0
2 0.01 0.01 -1.73472347598e-18
3 0.001 0.001 -2.16840434497e-19
4 0.0001 0.0001 -1.35525271561e-20
5 1e-05 1e-05 -1.69406589451e-21
6 1e-06 1e-06 -4.23516473627e-22

In this example, you can see that as the values get smaller, the difference between nearly equal numbers create non-zero results where the correct answer is zero.

S.Lott
  • 384,516
  • 81
  • 508
  • 779
1

There is a difference, but it is compiler dependent. At first on vs2003 (c++) I got no significant difference for double types (64 bit floating point). However running the tests again on vs2010, I detected a huge difference, up to factor 4 faster for multiplications. Tracking this down, it seems that vs2003 and vs2010 generates different fpu code.

On a Pentium 4, 2.8 GHz, vs2003:

  • Multiplication: 8.09
  • Division: 7.97

On a Xeon W3530, vs2003:

  • Multiplication: 4.68
  • Division: 4.64

On a Xeon W3530, vs2010:

  • Multiplication: 5.33
  • Division: 21.05

It seems that on vs2003 a division in a loop (so the divisor was used multiple times) was translated to a multiplication with the inverse. On vs2010 this optimization is not applied any more (I suppose because there is slightly different result between the two methods). Note also that the cpu performs divisions faster as soon as your numerator is 0.0. I do not know the precise algorithm hardwired in the chip, but maybe it is number dependent.

Edit 18-03-2013: the observation for vs2010

gast128
  • 1,223
  • 12
  • 22
  • I wonder if there's any reason a compiler couldn't replace e.g. `n/10.0` with an expression of the form `(n * c1 + n * c2)`? I would expect that on most processors a division will take longer than two multiplications and a division, and I believe that division by any constant can yield a correctly-rounded result in all cases using the indicated formulation. – supercat Jun 03 '14 at 20:55
1

I've read somewhere that multiplication is more efficient in C/C++; No idea regarding interpreted languages - the difference is probably negligible due to all the other overhead.

Unless it becomes an issue stick with what is more maintainable/readable - I hate it when people tell me this but its so true.

Christopher Lightfoot
  • 1,147
  • 1
  • 11
  • 27
1

I would suggest multiplication in general, because you don't have to spend the cycles ensuring that your divisor is not 0. This doesn't apply, of course, if your divisor is a constant.

Steve
  • 1,065
  • 15
  • 34
1

As with posts #24 (multiplication is faster) and #30 - but sometimes they are both just as easy to understand:

1*1e-6F;

1/1e6F;

~ I find them both just as easy to read, and have to repeat them billions of times. So it is useful to know that multiplication is usually faster.

Chris
  • 11
  • 1
0

After such a long and interesting discussion here is my take on this: There is no final answer to this question. As some people pointed out it depends on both, the hardware (cf piotrk and gast128) and the compiler (cf @Javier's tests). If speed is not critical, if your application does not need to process in real-time huge amount of data, you may opt for clarity using a division whereas if processing speed or processor load are an issue, multiplication might be the safest. Finally, unless you know exactly on what platform your application will be deployed, benchmark is meaningless. And for code clarity, a single comment would do the job!

Community
  • 1
  • 1
Jean-François
  • 374
  • 3
  • 8
0

Here's a silly fun answer:

x / 2.0 is not equivalent to x * 0.5

Let's say you wrote this method on Oct 22, 2008.

double half(double x) => x / 2.0;

Now, 10 years later you learn that you can optimize this piece of code. The method is referenced in hundreds of formulas throughout your application. So you change it, and experience a remarkable 5% performance improvement.

double half(double x) => x * 0.5;

Was it the right decision to change the code? In maths, the two expressions are indeed equivalent. In computer science, that does not always hold true. Please read Minimizing the effect of accuracy problems for more details. If your calculated values are - at some point - compared with other values, you will change the outcome of edge cases. E.g.:

double quantize(double x)
{
    if (half(x) > threshold))
        return 1;
    else
        return -1;
}

Bottom line is; once you settle for either of the two, then stick to it!

l33t
  • 18,692
  • 16
  • 103
  • 180
  • 1
    Downvote? How about a comment explaining your thoughts? This answer is definitely 100% relevant. – l33t Oct 08 '18 at 07:05
  • 1
    In computer science, multiply / divide of floating point values by powers of 2 is lossless, unless the value becomes denormalized or overflows. – Soonts Dec 09 '18 at 06:29
  • Since the floating point is not lossless at the time of division it doesn't really matter if your statement is true. Though I would be very surprised if it was. – l33t Dec 09 '18 at 12:27
  • 3
    “the floating point is not lossless at the time of division” only when you’re building with ancient compiler that emits deprecated x87 code. On modern hardware just having a float/double variable is lossless, either 32 or 64 bit IEEE 754: https://en.wikipedia.org/wiki/IEEE_754 Because of the way IEEE 754 works, when you divide by 2 or multiply by 0.5, you decreasing the exponent by 1, the rest of the bits (sign + mantissa) don’t change. And both `2` and `0.5` numbers can be represented in IEEE 754 exactly, without any loss of precision (unlike e.g. `0.4` or `0.1`, they can’t). – Soonts Dec 09 '18 at 15:23
0

Java android, profiled on Samsung GT-S5830

public void Mutiplication()
{
    float a = 1.0f;

    for(int i=0; i<1000000; i++)
    {
        a *= 0.5f;
    }
}
public void Division()
{
    float a = 1.0f;

    for(int i=0; i<1000000; i++)
    {
        a /= 2.0f;
    }
}

Results?

Multiplications():   time/call: 1524.375 ms
Division():          time/call: 1220.003 ms

Division is about 20% faster than multiplication (!)

PiotrK
  • 4,210
  • 6
  • 45
  • 65
  • 1
    To be realistic, you should test `a = i*0.5`, not `a *= 0.5`. That's how most programmers will be using the operations. – Blazemonger Dec 08 '11 at 18:49
  • 1
    These functions don't use the result; this is unlikely to be a valid microbenchmark. They could easily have optimized away the division work inside the loop. – Peter Cordes Jan 20 '23 at 19:24
-1

Well, if we assume that an add/subtrack operation costs 1, then multiply costs 5, and divide costs about 20.

matma
  • 1,104
  • 1
  • 10
  • 17
  • Where did you get these numbers from? experience? gut feeling? article on the internet? how would they change for different data types? – kroiz Feb 12 '14 at 09:30
-3

Technically there is no such thing as division, there is just multiplication by inverse elements. For example You never divide by 2, you in fact multiply by 0.5.

'Division' - let's kid ourselves that it exists for a second - is always harder that multiplication because to 'divide' x by y one first needs to compute the value y^{-1} such that y*y^{-1} = 1 and then do the multiplication x*y^{-1}. If you already know y^{-1} then not calculating it from y must be an optimization.

satnhak
  • 9,407
  • 5
  • 63
  • 81
  • 3
    Which completely ignores the reality of both commands existing in the silicon. – NPSF3000 Feb 11 '12 at 14:28
  • @NPSF3000 - I don't follow. Under the assumption that both operations exists, it simply asserts that the division operation implicitly involves the computation of a multiplicative inverse and a multiplication, which will always be harder than just doing a single multiplication. The silicon is an implementation detail. – satnhak Feb 13 '12 at 09:55
  • @ BTyler. If both commands exist in the silicon, and both commands take the same number of cycles [as one would expect] than how relatively complex the instructions are is completely irrelevant from a performance POV. – NPSF3000 Feb 16 '12 at 01:49
  • @NPSF3000 - but they don't both take the same number of cycles do they because multiplication is faster. – satnhak Feb 16 '12 at 10:00