python - 续对数运算 : floor operator on run-length encoded terms

标签 python algorithm continued-fractions

我正尝试在 Bill Gosper 的 continued logarithms 上实现基本算术,这是连分数的“突变”,允许术语协同例程发出和使用非常小的消息,即使是非常大或非常小的数字。

可逆算术,例如 {+,-,*,/} 至少在一元表示中被 Gosper 相当直接地描述,但我很难实现有效截断除法运算信息的模运算符。

我意识到模运算符大部分可以用我已有的操作来定义:

a mod b == a - b * floor(a / b)

留下我唯一的问题。

我还读到连续对数的游程编码格式有效地描述了

'... the integer part of the log base 2 of the number remaining to be described.'

因此,立即产生第一项(通过)会产生到目前为止正确的输出,但还有很大一部分有待确定,我认为这需要某种进位机制。

我编写了以下代码来测试输入项和预期的输出项,但我主要是在寻找实现 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)

How can I implement the floor operator in the spirit of continued fraction arithmetic by consuming terms only when necessary and emitting terms right away, and especially only using the run-length encoded format (in binary) rather than the unary expansion Gosper tends to describe.

最佳答案

通过假设游程编码中的下一个系数是无限的,您可以获得下限。通过假设下一项为 1,您可以获得上限。

您可以简单地处理尽可能多的游程长度编码系数,直到您知道下限和上限都在半开区间 [N, N + 1) 内。在这种情况下,您知道连续对数的底数是 N。这类似于 Bill Gosper 在链接文档开头所做的事情。

但是请注意,此过程不一定会终止。例如,当您将 sqrt(2) 乘以 sqrt(2) 时,您当然会得到数字 2。但是,sqrt(2) 的连对数是无限的。要评估乘积 sqrt(2) * sqrt(2),您将需要所有系数才能知道最终结果为 2。对于任何有限数量的项,您无法确定乘积是否小于 2 或等于至少等于它。

请注意,此问题并非特定于连续对数,但它是任何系统中都会出现的基本问题,在该系统中,您可以有两个表示无限的数字,但乘积可以用有限数量的系数表示.

为了说明这一点,假设这些协程不吐出游程长度编码值,而是吐出十进制数字,我们想要计算 floor(sqrt(2) * sqrt(2))。经过多少步我们可以确定乘积至少为 2?让我们取 11 位数字,看看会发生什么: 1.41421356237 * 1.41421356237 = 1.9999999999912458800169

正如您可能猜到的那样,我们任意接近 2,但永远不会“达到”2。确实,在不知道数字源是 sqrt(2) 的情况下,可能恰好数字在该点之后终止并且乘积最终低于 2。类似地,所有后续数字可能都是 9,这将导致乘积略高于 2。

(一个更简单的示例是对产生 0.9999 的例程进行发言...)

因此,在这类任意精度的数值系统中,您最终可能会遇到只能计算某个区间(N - epsilon,N + epsilon)的情况,在这种情况下,您可以使 epsilon 任意小,但永远不会等于零。无法对这个表达式进行解释,因为通过所采用的数值方法无法确定实际值最终会低于还是高于 N。

关于python - 续对数运算 : floor operator on run-length encoded terms,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47243679/

相关文章:

python - 查找(或暴力破解)值列表和数学运算的数学表达式

c++ - 作为有理数的 float 的精确值

python - 在 django 中将字段更改为外键后出现未知列错误

python - MySQL、SQLAlchemy、Flask 和 Flask.ext.script 的问题 — create_all() 不创建表

c# - 可以在比 O(n^2) 时间更好的时间内做到这一点吗?

Python 2.7 - 连分数扩展 - 理解错误

python - 连续分数到分数故障

python - 某个 skiprows 参数后的 pandas 内存错误

python - 目录错误: [Errno 21] Is a directory ( in AudioSegment)

java - 删除数组中的行和列列表后找到最大间隙