views:

3170

answers:

19

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.

+1  A: 

I have always learned that multiplication is more efficient.

Gamecat
i have always learned to let the compiler figure it out.
Dustin Getz
"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.
+3  A: 

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
this optimization is automatically performed behind the scenes in any modern compiler.
Dustin Getz
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.
widgisoft
That didn't print anywhere close to what I imagined; Nevermind.
widgisoft
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).
widgisoft
+2  A: 

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

Dan Hewett
+31  A: 

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
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
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
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 Swangren
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.
+1  A: 

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.

widgisoft
A: 

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

matma
+7  A: 

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?

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
Division is accurate if you're dividing by whole numbers.
plinth
Floating-point division with denominator > numerator must introduce meaningless values in the low-order bits; division usually reduces accuracy.
S.Lott
+6  A: 

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
+2  A: 

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
+1  A: 

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
+25  A: 

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
Thanks for the tip on using the time command for benchmarking!
Edmundito
+6  A: 

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
+18  A: 

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
that's not the full Knuth quote; see http://en.wikipedia.org/wiki/Optimization_(computer_science)#When_to_optimize
Jason S
No, there are about 40 different quotes on the subject from as many different sources. I kind of piece a few together.
Bill K
+2  A: 

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  A: 

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
A: 

what the heck is a subtrack operation?

+1  A: 

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
That code is not clear at all.
Charlie Somerville
+4  A: 

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