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