I'll expand on my comment.
charting[min_, max_] := Charting`ScaledTicks[{Identity, Identity}][min, max]
// #[[;; , {1, 2}]] & // Cases[#, {_, _?NumberQ}] &
is in some respects equivalent to
finddivs[min_, max_] := FindDivisions[{min, max}, 6]
For example
charting[1.1, 5.9]
finddivs[1.1, 5.9]
charting[0.9, 6.1]
finddivs[0.9, 6.1]
returns:
{{2., 2}, {3., 3}, {4., 4}, {5., 5}}
{1, 2, 3, 4, 5, 6}
{{1., 1}, {2., 2}, {3., 3}, {4., 4}, {5., 5}, {6., 6}}
{0, 1, 2, 3, 4, 5, 6, 7}
Neither of them is exact; Mathematica does not find intervals like {0., 0.6, 1.2, 2.4, 3.0}
to be "nice".
Given your specification (numbers divisible by 5, starting from 0), the easiest is to do:
sixTicks[max_] := Transpose[{#, #}] &[Range[0., max, max/5]
and to modify ticksHelper
like so:
ticksHelper[min_, max_] :=
Module[{out = sixTicks[max]},
out[[-1, -1]] = "> " <> ToString@max;
out]
Update 10.03.17
At first I suggested an undocumented, internal function
Charting`ScaledTicks
to generate the necessary ticks semi-automatically and then to post-process the output to get the more detailed specifications required by the OP. Usually -- when working internally -- this function takes the plot range and generates a nice set of ticks for that range. E.g.,
(Charting`ScaledTicks[{Identity, Identity}][-0.132, 1.145]
// #[[;; , ;; 2]] & (* strips tick style specs *)
// DeleteCases[#, {_, _Spacer}] &) (* removes minor ticks *)
{{0.,0},{0.25,0.25},{0.5,0.50},{0.75,0.75},{1.,1.00}}
This leaves us with a very simple list of {position, label}
tuples. Note, how I fed the function an awkward range like (-0.132, 1.145)
but it tried to return a list of sufficiently round numbers. By the way, it also formatted each number to have two digits after the decimal. Peeking at the FullForm
we can see that the 0.50
(list element [[3,2]]
) is actually
NumberForm[0.5, {DirectedInfinity[1], 2}]
As I have mentioned, FindDivisions[{min, max}, n]
does a similar thing, subdividing a given range into approximately n
intervals.
This is of somewhat limited use for the OP, since these automatic functions -- among other things -- may or may not indeed include a tick at max
.
When fine control is desired, there are packages for this, such CustomTicks
and/or for such a specific use case it may be easier to simply roll a quick function. Hopefully, this update will describe in enough detail, how to do it, rather than just do it.
As mentioned before, OP has
min = 0;
max = ...;
where max (or perhaps, rather, 10 * max
) is divisible by 5. To properly describe the procedure, I'll verbosely rewrite the helper functions sixTicks
and ticksHelper
.
First we need the positions of the ticks, which I immediately generate to machine precision; these are quite simply {0, max/5, 2max/5, ...}
or
positions = Range[0., max, max/5];
Next, we need the labels at these positions. I, generally, prefer casting them to strings, like so:
labels = ToString /@ positions
and then the ticks will be
Transpose[{positions, labels}]
There's two things to handle: OP wants the last tick label to be > max
, which is trivially done by
labels[[-1]] = "> " <> labels[[-1]]
OP also wants the numbers to have equal number of digits after the decimal point, which is slightly harder. In fact, a very quick search couldn't find an easy way to ask Mathematica
Ok, we have a machine-precision number like 0.0032
. Sure, the precision of it is 15.84
or so, but how many digits are there really, for us humans?
and to get the obvious answer 4
. Well, one quick and dirty approach is to multiply by 10, compare the result to Floor[result]
, if not, multiply by 10 again, and so on.
Length[NestWhileList[10 # &, 0.25, Floor@# != # &]] - 1
Length[NestWhileList[10 # &, 0.0032, Floor@# != # &]] - 1
(* 2 *)
(* 4 *)
We know for sure, that the longest decimal representation of our list of numbers will be no longer than the representation of max/5
. So let's start putting all this together in a Module
ticks[max_] := Module[
{
positions = Range[0., max, max / 5],
precision = Length[NestWhileList[10 # &, max / 5, Floor@# != # &]] - 1,
labels},
If[precision > 0,
labels = ToString /@ (NumberForm[#, {Infinity, precision}] & /@ positions)];
If[precision == 0,
labels = ToString /@ Floor[positions]];
labels[[-1]] = "> " <> labels[[-1]];
Transpose[{positions, labels}]
]
Most things here I've covered. To get the correct formatting of numbers, I've borrowed the function used in the output of Charting`ScaledTicks
, i.e. NumberForm
. NumberForm[0.016, {Infinity, 4}]
will print 0.016
with 4 digits to the right of the decimal, i.e. 0.0160
. The two If
statements handle the special case that all labels are integers, so Floor
turns machine-preicsion numbers like 1.
into integers like 1
. For integers NumberForm
is unnecessary.
Plot[Sin[200 x], {x, -0.02, 0.02},
Frame -> True, FrameTicks -> {{None, None}, {None, ticks[0.016]}}]
I hope, this answer doesn't give the fish, but also the fishing rod.
FindDivisions
. The charting function is good if you don't know in advance a decent way to subdivide your range. $\endgroup$