The implementation shown below is in python. Most elements of it will translate easily and directly to C# if you are skilled in both languages. A few statements may require a series of if
statements or a different approach.
In the program, the last four lines are the main program. As shown, main has a loop to generate 80 test cases, with sizes increasing geometrically from 0.04 up to about 200. If you want to test more coarsely, change 40 (number of sizes) to a smaller number and 1.24 (geometric ratio) to a bigger number. For each size tested, main calls stepShow
two times, first with a test range from 10% of size
up to 110% of size
, then with a test range from -28% to 82%. stepShow
is a test routine that calls stepCalc
, which is the routine that embodies an algorithm to calculate leftTick
and tickSize
, which are the location of the leftmost tick and the interval between ticks.
stepCalc
begins with span = max(hiVal,0) - min(loVal,0)
which ensures that x=0 will fit into the span of ticks. Then decade = 10**(math.log(span/6.0)//math.log(10))
computes the greatest power of 10 not greater than 1/6 of the span. (Python's //
operator returns an integer result and **
represents exponentiation.) multis = (1,1.5,2,3,5,10) if decade==1 else (1,2,5,10)
sets the tuple multis
to (1,1.5,2,3,5,10) if tick size is likely to be between 1 and 10, but otherwise sets it to (1,2,5,10). Code in the loop for m in multis:
computes tickSize
and leftTick
values; when they are big enough, it breaks out of the loop and returns them.
In the output of this program, the two test cases for each size will ordinarily have the same tickSize
, but of course leftTick
is zero for the first case and negative for the second. Here are a few example lines. (Full output is shown after the program.) Each 5-number group includes values of leftTick, loVal, hiVal, rightTick, tickSize
.
0.000 0.101 1.109 1.200 0.200 -0.500 -0.282 0.826 2.500 0.500
0.000 0.238 2.621 3.000 0.500 -1.000 -0.667 1.954 2.000 0.500
0.000 0.295 3.250 6.000 1.000 -1.000 -0.827 2.423 5.000 1.000
0.000 0.563 6.197 9.000 1.500 -3.000 -1.577 4.619 6.000 1.500
0.000 0.866 9.528 12.000 2.000 -4.000 -2.425 7.103 8.000 2.000
0.000 1.074 11.815 12.000 2.000 -6.000 -3.007 8.807 12.000 3.000
For some sizes, tickSize
differs between the two cases, as in the first and last of the example lines above. Although the overall span is the same in both test cases, 110% of size
, a larger tickSize
value is needed when the 0 tick is not at the end of the range if loVal
or hiVal
no longer both fit into the span covered by the smaller tickSize
value. Including 10 in the multis
tuple handles this case.
def stepCalc(loVal, hiVal):
import math
span = max(hiVal,0) - min(loVal,0) # have to have 0 in span
decade = 10**(math.log(span/6.0)//math.log(10))
multis = (1,1.5,2,3,5,10) if decade==1 else (1,2,5,10)
for m in multis:
tickSize = m * decade
cover = 6.0 * tickSize;
leftTick = 0 if loVal >= 0 else -cover if hiVal <= 0 else (loVal//tickSize)*tickSize
if leftTick+cover >= hiVal: break
return (leftTick, tickSize)
def stepShow(loVal, hiVal):
(leftTick, tickSize) = stepCalc(loVal, hiVal)
return ' {:7.3f} {:7.3f} {:7.3f} {:7.3f} {:7.3f} '.format(leftTick, loVal, hiVal, leftTick+6*tickSize, tickSize)
size = 0.04
for i in range(40):
print stepShow(0.1*size, 1.1*size), stepShow(-0.28*size, 0.82*size)
size *= 1.24
The code shown above does not try to symmetrize the location of the ticks. If you want to do that, you could add code before return (leftTick, tickSize)
to decrease leftTick
by multiples of tickSize
while there are more multiples of tickSize
above hiVal
than below loVal
.
Program Output:
0.000 0.004 0.044 0.060 0.010 -0.020 -0.011 0.033 0.040 0.010
0.000 0.005 0.055 0.060 0.010 -0.020 -0.014 0.041 0.040 0.010
0.000 0.006 0.068 0.120 0.020 -0.020 -0.017 0.050 0.100 0.020
0.000 0.008 0.084 0.120 0.020 -0.040 -0.021 0.063 0.080 0.020
0.000 0.009 0.104 0.120 0.020 -0.040 -0.026 0.078 0.080 0.020
0.000 0.012 0.129 0.300 0.050 -0.050 -0.033 0.096 0.250 0.050
0.000 0.015 0.160 0.300 0.050 -0.050 -0.041 0.119 0.250 0.050
0.000 0.018 0.198 0.300 0.050 -0.100 -0.050 0.148 0.200 0.050
0.000 0.022 0.246 0.300 0.050 -0.100 -0.063 0.183 0.200 0.050
0.000 0.028 0.305 0.600 0.100 -0.100 -0.078 0.227 0.500 0.100
0.000 0.034 0.378 0.600 0.100 -0.100 -0.096 0.282 0.500 0.100
0.000 0.043 0.469 0.600 0.100 -0.200 -0.119 0.350 0.400 0.100
0.000 0.053 0.581 0.600 0.100 -0.200 -0.148 0.433 0.400 0.100
0.000 0.066 0.721 1.200 0.200 -0.200 -0.184 0.537 1.000 0.200
0.000 0.081 0.894 1.200 0.200 -0.400 -0.228 0.666 0.800 0.200
0.000 0.101 1.109 1.200 0.200 -0.500 -0.282 0.826 2.500 0.500
0.000 0.125 1.375 3.000 0.500 -0.500 -0.350 1.025 2.500 0.500
0.000 0.155 1.705 3.000 0.500 -0.500 -0.434 1.271 2.500 0.500
0.000 0.192 2.114 3.000 0.500 -1.000 -0.538 1.576 2.000 0.500
0.000 0.238 2.621 3.000 0.500 -1.000 -0.667 1.954 2.000 0.500
0.000 0.295 3.250 6.000 1.000 -1.000 -0.827 2.423 5.000 1.000
0.000 0.366 4.030 6.000 1.000 -2.000 -1.026 3.004 4.000 1.000
0.000 0.454 4.997 6.000 1.000 -2.000 -1.272 3.725 4.000 1.000
0.000 0.563 6.197 9.000 1.500 -3.000 -1.577 4.619 6.000 1.500
0.000 0.699 7.684 9.000 1.500 -3.000 -1.956 5.728 6.000 1.500
0.000 0.866 9.528 12.000 2.000 -4.000 -2.425 7.103 8.000 2.000
0.000 1.074 11.815 12.000 2.000 -6.000 -3.007 8.807 12.000 3.000
0.000 1.332 14.650 18.000 3.000 -6.000 -3.729 10.921 12.000 3.000
0.000 1.651 18.166 30.000 5.000 -5.000 -4.624 13.542 25.000 5.000
0.000 2.048 22.526 30.000 5.000 -10.000 -5.734 16.792 20.000 5.000
0.000 2.539 27.932 30.000 5.000 -10.000 -7.110 20.822 50.000 10.000
0.000 3.149 34.636 60.000 10.000 -10.000 -8.816 25.819 50.000 10.000
0.000 3.904 42.948 60.000 10.000 -20.000 -10.932 32.016 40.000 10.000
0.000 4.841 53.256 60.000 10.000 -20.000 -13.556 39.700 40.000 10.000
0.000 6.003 66.037 120.000 20.000 -20.000 -16.810 49.228 100.000 20.000
0.000 7.444 81.886 120.000 20.000 -40.000 -20.844 61.043 80.000 20.000
0.000 9.231 101.539 120.000 20.000 -40.000 -25.846 75.693 80.000 20.000
0.000 11.446 125.908 300.000 50.000 -50.000 -32.049 93.859 250.000 50.000
0.000 14.193 156.127 300.000 50.000 -50.000 -39.741 116.385 250.000 50.000
0.000 17.600 193.597 300.000 50.000 -50.000 -49.279 144.318 250.000 50.000