# Quickly reducing the number of decimal digits for a set of real numbers

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.

• User, what version of Mathematica are you using? I am using version 7 and get timings that are within an order of yours. Another user reports timings that are an order of magnitude faster. Sep 19 '13 at 6:13
• @Mr.Wizard I am using version 9.0.1.0 on a 64-bit operating system. Sep 19 '13 at 6:16
• User, please try the code in my answer and report your timings after packing; I believe you may get a much larger improvement than I did. Sep 19 '13 at 6:32
• Evaluating SeedRandom[42]; testvalues = RandomReal[1., {100, 2}]; For[i = 1, i <= 100000, i++, Round[testvalues, 0.1]]// AbsoluteTiming on my system gives {0.713849, Null} which is way faster than what the OP is seeing. I'm using V.9.0.1 on OS X 10.6.8 on a three year old iMac with a 2.93 MHz i7 iMac. I am very puzzled by the discrepancy. Sep 19 '13 at 6:40
• @Mr.Wizard I ran your code for Packing: unpacked values gives {11.361650, Null} and packed values gives {0.640037, Null}. Hmmm.... Sep 19 '13 at 6:50

### Packing

You should make sure that your data is packed if at all possible:

DeveloperPackedArrayQ[testvalues]
False
packedvalues = DeveloperToPackedArray@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.

• I have {11.361650, Null} for unpacked values and {0.640037, Null} for packed values. Why am I seeing an order of magnitude speedup relative to you? Sep 19 '13 at 6:51
• Data Shape: I get {0.876050, Null}. Sep 19 '13 at 6:52
• SetAccuracy: I get {2.585148, Null}, similar to your numbers. Sep 19 '13 at 6:52
• It looks like Packing solves my speed issue, but the lesson is that this only works in v9? Sep 19 '13 at 6:53
• @george2079 My point is that the numbers should have been packed on generation or at least before further operations, therefore no, I do not believe it should have been included in the loop. Sep 19 '13 at 18:39

For this example I get a 4-fold speed increase using Map:

Round[testvalues, .1]

(* ~12 sec *)

Map[Round[#, .1] &, testvalues, {2}]

(* ~3 sec *)

Edit, note if we do this with packedarrays the direct round applicaiton wins..

Map[Round[#, .1] &, packedvalues, {2}]

(* 3 sec *)

Round[packedvalues, .1]

(* 0.9 sec *)

If you include the packing operation in the timing its still pretty good..

Round[(Developer`ToPackedArray@testvalues), .1]

(1.3 sec)

... All timing with the For loop in the original Question ...

• What testvalues are you using? Surely not the 100x2 array with those timings. Sep 21 '13 at 0:20