Спасибо всем, кто ответил, но я закончил тем, что написал свое собственное решение, потому что другие были не совсем тем, что мне было нужно. Я пытаюсь усреднить имена ключей движка приложений, и, изучив их немного подробнее, я обнаружил, что они фактически допускают любые 7-битные символы ASCII в именах. Кроме того, я не мог полагаться на решения, которые сначала преобразовывали имена ключей в числа с плавающей запятой, потому что подозревал, что точности с плавающей запятой просто недостаточно.
Чтобы получить среднее значение, сначала сложите два числа вместе, а затем разделите на два. Это обе такие простые операции, что я решил просто сделать функции для добавления и деления базовых 128 чисел, представленных в виде списков. Это решение еще не использовалось в моей системе, поэтому я все еще могу найти некоторые ошибки в нем. Кроме того, это может быть намного короче, но это просто то, что мне нужно было сделать, вместо того, чтобы пытаться сделать его идеальным.
# Given two lists representing a number with one digit left to decimal point and the
# rest after it, for example 1.555 = [1,5,5,5] and 0.235 = [0,2,3,5], returns a similar
# list representing those two numbers added together.
#
def ladd(a, b, base=128):
i = max(len(a), len(b))
lsum = [0] * i
while i > 1:
i -= 1
av = bv = 0
if i < len(a): av = a[i]
if i < len(b): bv = b[i]
lsum[i] += av + bv
if lsum[i] >= base:
lsum[i] -= base
lsum[i-1] += 1
return lsum
# Given a list of digits after the decimal point, returns a new list of digits
# representing that number divided by two.
#
def ldiv2(vals, base=128):
vs = vals[:]
vs.append(0)
i = len(vs)
while i > 0:
i -= 1
if (vs[i] % 2) == 1:
vs[i] -= 1
vs[i+1] += base / 2
vs[i] = vs[i] / 2
if vs[-1] == 0: vs = vs[0:-1]
return vs
# Given two app engine key names, returns the key name that comes between them.
#
def average(a_kn, b_kn):
m = lambda x:ord(x)
a = [0] + map(m, a_kn)
b = [0] + map(m, b_kn)
avg = ldiv2(ladd(a, b))
return "".join(map(lambda x:chr(x), avg[1:]))
print average('a', 'z') # m@
print average('aa', 'zz') # n-@
print average('aa', 'az') # am@
print average('cat', 'doggie') # d(mstr@
print average('google', 'microsoft') # jlim.,7s:
print average('microsoft', 'google') # jlim.,7s: