#!/usr/bin/python

import math

# define error functions and midpoint functions

def error_ratio(mid, minmax):
    '''The ratio between the rounded value and the actual value
       | n / r(n) - 1 | 
    '''
    return abs(minmax / mid - 1.0)

def mid_min_error_ratio(l, h):
    '''Minimise the ratio between the rounded value and the actual value
    '''
    return math.sqrt(l * h)

def error_difference(mid, minmax):
    '''The difference between the rounded value and the actual value
       | n - r(n) |
    '''
    return abs(minmax - mid)

midpoint = mid_min_error_ratio
tests = [error_ratio, error_difference]

# Start with an interval representing the current rounding
# we round to 3 significant figures, but we need an extra digit of precision
# to capture the values around the low end
precision = 3+1
low = math.pow(10.0, precision - 1)
high = low*10.0
values = (high - low) / 10.0
bounds = [low, high]
# Create at least as many values as are in the existing scheme
# (an appropriate midpoint function should be used to choose whether to round
# to the lower or higher value)
scale = (high-low)/values

# increase the values geometrically between low and high
step = math.pow(high/low, 1.0/values)
print step
next = low/scale
bounds = []
while next <= (high/scale + 1):
    bounds.append(next)
    next *= step

# round to the nearest integer
bounds = [int(round(b*scale, 0)) for b in bounds]

# increase the values linerly between low and high
#bounds = range(int(low), int(high)+1)

print len(bounds)
b_prev = None
for b in bounds:
    comparison = "{:.0f}".format(b)
    if b_prev is not None:
        for test in tests:
            comparison += " {:.5f}".format(test(midpoint(b_prev, b), b))
    print comparison
    b_prev = b

# chop off the upper bound: it belongs to the next decile
if bounds[-1] == high:
    del bounds[-1]

print bounds
