programming - Is this the most efficient way to round approximate integers to integers while leaving other Reals untouched?
This might seem like an overly simple question, but I need to specify custom plot tick marks as integers (no trailing decimal point) if they are approximately integers, but not if they are not. Using Rationalize
on all the tick values won't work because I don't want ticks in the form of $\frac{3}{2}$.
Consider:
roundif = If[Chop[# - Floor[#]] == 0, Rationalize[#], #] &
Some tests to show it works as intended:
roundif /@ {-1., -1, 0, 0.5, 1500, 1501., 1501.2}
(* {-1, -1, 0, 0.5, 1500, 1501, 1501.2} *)
roundif /@ Range[-3, 3, 0.5]
(* {-3, -2.5, -2, -1.5, -1, -0.5, 0, 0.5, 1, 1.5, 2, 2.5, 3} *)
(Of course, I could make it a normal SetDelayed
function and make its Attributes
include Listable
.)
Timing seems to be linear in the length of the list and the number of times it is performed.
testdata = Range[-30, 30, 0.5];
Do[roundif /@ testdata, {10000}]; // AbsoluteTiming
{5.8656000, Null}
Is this the most efficient way to do this? Have I missed some subtlety?
Answer
Stan Wagon presents a little utility function in his book Mathematica in Action called IntegerChop[]
. Here's a slightly wrinkled version:
IntegerChop = With[{r = Round[#]}, r + Chop[# - r]] &;
You might wish to do comparisons yourself (the computer I am using does not have Mathematica).
Here are some benchmarks:
Do[roundif /@ testdata, {10000}]; // AbsoluteTiming
(* ==> {4.7382710, Null} *)
Do[IntegerChop /@ testdata, {10000}]; // AbsoluteTiming
(* ==> {4.6512660, Null} *)
So basically no difference.
Comments
Post a Comment