我正在尝试在 Bill Gosper 的连续对数上实现基本算术,这是连续分数的“突变”,允许术语协同例程即使在非常大或非常小的数字上也能发出和消耗非常小的消息。
可逆算术,例如 {+,-,*,/} 至少在一元表示中由 Gosper 相当直接地描述,但我很难实现有效地从除法运算中截断信息的模运算符。
我已经意识到模运算符主要可以用我已经拥有的操作来定义:
a mod b == a - b * floor(a / b)
留下我唯一的问题是地板。
我还读到连续对数的行程编码格式有效地描述了
'...待描述的剩余数字的以 2 为底的对数的整数部分。
因此,立即产生第一项(通过)到目前为止会产生正确的输出,但仍有很大一部分有待确定,我认为这需要某种进位机制。
我编写了以下代码来测试输入项和预期的输出项,但我主要是在寻找实现 floor 背后的高级算法思想。
输出对的示例输入 (1234 / 5) 是
输入:[7, 0, 3, 0, 0, 0, 0, 1, 3, 3, 1]
输出:[7, 0, 3, 1, 4, 2, 1, 1]
from fractions import Fraction
def const(frac):
""" CL bistream from a fraction >= 1 or 0. """
while frac:
if frac >= 2:
yield 1
frac = Fraction(frac, 2)
else:
yield 0
frac -= 1
frac = Fraction(1, frac) if frac else 0
def rle(bit_seq):
""" Run-length encoded CL bitstream. """
s = 0
for bit in bit_seq:
s += bit
if not bit:
yield s
s = 0
def floor(rle_seq):
""" RLE CL terms of the greatest integer less than rle_seq. """
#pass
yield from output
""" Sample input/output pairs for floor(). """
num = Fraction(1234)
for den in range(1, int(num)+1):
input = list(rle(const(num / den)))
output = list(rle(const(num // den))) # Integer division!
print("> ", input)
print(">> ", output)
print(">>*", list(floor(input)))
print()
assert(list(floor(input)) == output)
我如何才能本着连分数算术的精神实现地板运算符,仅在必要时使用项并立即发出项,尤其是仅使用游程编码格式(二进制)而不是 Gosper 倾向于描述的一元展开。