How can I quickly convert a number with $n$ decimal points to a number of with $m$ decimal points? Round works, however, it is slower than I would like. This example rounds a set of $100$ real numbers to $0.1$ decimal precision:
testvalues = Table[{RandomReal[], RandomReal[]}, {i, 1, 100}]
t1 = AbsoluteTime[];
For[i = 1, i <= 10^5, i++,
Round[testvalues, 0.1];
];
t2 = AbsoluteTime[];
t2 - t1
Takes $\approx 11.87$ seconds on my 3.47 GHz CPU. Floor and Ceiling take a commensurate amount of time.
Answer
Packing
You should make sure that your data is packed if at all possible:
Developer`PackedArrayQ[testvalues]
False
packedvalues = Developer`ToPackedArray@testvalues;
This at least speeds things a bit (timings in version 7 under Windows):
Do[Round[testvalues, 0.1], {10^5}] // AbsoluteTiming
Do[Round[packedvalues, 0.1], {10^5}] // AbsoluteTiming
{7.0500098, Null}
{6.0500085, Null}
In version 9, and possibly 8, you should see a much greater improvement from packing that I experienced here in version 7. Other users are reporting well over an order of magnitude improvement in later versions.
Note that if you had generated the values with RandomReal[1, {100, 2}] they would have been packed to start with.
Data shape
In version 7, where the Round operation is handled by the Mathematica Kernel rather than the Intel MKL transposing the values before rounding makes a considerable difference:
Do[Round[packedvalues\[Transpose], 0.1]\[Transpose], {10^5}] // AbsoluteTiming
{3.8900054, Null}
SetAccuracy
Also applicable to version 7, an alternative that may be acceptable it is to use SetAccuracy which on my system this about twice as fast:
tvalues = packedvalues\[Transpose];
Do[SetAccuracy[tvalues, 2], {10^5}] // AbsoluteTiming
{1.7961027, Null}
Note that users of more recent versions will find that Round on a packed array is faster than SetAccuracy.
Comments
Post a Comment