There are many technical challenges that make exact bit-for-bit reproducibility of computational results extremely hard to achieve.
At the software level, changes to the code or any of the libraries used by the code can obviously cause different results to be produced. You'd be surprised by the number of support libraries that can end up linked into a typical scientific code.
At a lower level, recompiling any of the code or any of the libraries used by the code with a new compiler or with different compiler optimizations turned on can also cause problems. One reason is that various operations in the code might be performed in a different order when the code is recompiled. Since floating point addition is not associative (a+b)+c <> a+(b+c), this can give different results.
OK, so what if we preserve the entire software environment (OS, libraries, and compiled code) by (e.g.) burning it on to a bootable CD-Rom that will run the code. Now can we be sure that we'll get the same results if we run this code on a different computer?
Surprisingly, some codes actually vary the order of computations based on aspects of the particular processor model that they're running on. For example, optimized linear algebra libraries typically break up matrix multiplications to work on blocks that will fit into cache. When Intel releases a new microprocessor with a bigger cache the code might dynamically adjust the block size, resulting in arithmetic that is performed in a different order and giving different results. Other codes dynamically adjust the order of computations based on the amount of available memory- if you run the code on a computer with more memory that could well cause the arithmetic to be done in a different order and thus give different results.
Things get amazingly more complicated when you throw in multithreaded code, since the exact execution history of the different threads is often non-deterministic and this can again cause arithmetic operations to be performed in a different order from one run to the next.
In practice the most that you can really hope for are results that are similar from one machine to the next, up to the accuracy tolerances of the algorithms used. e.g. if I have a root finding problem and use bisection to get a root to within +-1.0e-10, then I should be happy as long as different machines are producing answers that agree within that tolerance.