当前位置:  开发笔记 > 编程语言 > 正文

"近似的"最大公约数

如何解决《"近似的"最大公约数》经验,为你挑选了4个好方法。

例如,假设您有一个浮点数列表,它大约是常见数量的倍数

2.468,3.700,6.1699

这大约是1.234的倍数.您如何描述这种"近似gcd",您将如何进行计算或估算呢?

与我对这个问题的回答密切相关.



1> David Lehavi..:

您可以运行Euclid的gcd算法,其中任何小于0.01(或您选择的少数)都是伪0.使用您的数字:

3.700 = 1 * 2.468 + 1.232,
2.468 = 2 * 1.232 + 0.004. 

所以前两个数字的伪gcd是1.232.现在你用你的最后一个数字取gcd:

6.1699 = 5 * 1.232 + 0.0099.

所以1.232是伪gcd,而mutiples是2,3,5.要改善此结果,您可以对数据点进行线性回归:

(2,2.468), (3,3.7), (5,6.1699).

斜率是改进的伪gcd.

警告:第一部分是算法在数值上不稳定 - 如果从非常脏的数据开始,你就遇到了麻烦.



2> Sparr..:

将您的测量值表示为最低值的倍数.因此,您的列表变为1.00000,1.49919,2.49996.这些值的小数部分将非常接近1/Nth,因为N的某个值取决于您的最低值与基频的接近程度.我建议循环增加N,直到找到足够精确的匹配.在这种情况下,对于N = 1(即,假设X = 2.468是您的基频),您会发现标准偏差为0.3333(三个值中的两个是X*1的0.5.),这是不可接受的高.对于N = 2(即,假设2.468/2是您的基频),您会发现标准差几乎为零(所有三个值都在.X/2倍数的.001内),因此2.468/2是您的近似值GCD.

我的计划中的主要缺陷是,当最低测量值最准确时,它最有效,但情况可能并非如此.这可以通过多次执行整个操作来减轻,每次丢弃测量列表上的最低值,然后使用每个过程的结果列表来确定更精确的结果.改善结果的另一种方法是调整GCD以最小化GCD的整数倍与测量值之间的标准偏差.



3> Darius Bacon..:

这让我想起了找到实数的理性数近似值的问题.标准技术是持续分数扩展:

def rationalizations(x):
    assert 0 <= x
    ix = int(x)
    yield ix, 1
    if x == ix: return
    for numer, denom in rationalizations(1.0/(x-ix)):
        yield denom + ix * numer, numer

我们可以直接将它应用于Jonathan Leffler和Sparr的方法:

>>> a, b, c = 2.468, 3.700, 6.1699
>>> b/a, c/a
(1.4991896272285252, 2.4999594813614263)
>>> list(itertools.islice(rationalizations(b/a), 3))
[(1, 1), (3, 2), (925, 617)]
>>> list(itertools.islice(rationalizations(c/a), 3))
[(2, 1), (5, 2), (30847, 12339)]

从每个序列中挑选出第一个足够好的近似值.(3/2和5/2在这里.)或代替直接比较3.0/2.0〜1.499189 ......,你会发现比六百十七分之九百二十五使用更大的整数比3/2,使3/2的绝佳场所停止.

你所分割的数字中的哪一个并不重要.(使用A/B和C/B你2/3和5/3,例如).一旦你有整数比,你可以细化基本使用shsmurfy的线性回归的隐含估值.大家都赢了!



4> shsmurfy..:

我假设你的所有数字都是数值的倍数.对于我的其余解释,A将表示您尝试查找的"根"频率,B将是您必须开始的数字数组.

你要做的是表面上类似于线性回归.您正在尝试找到线性模型y = mx + b,它可以最小化线性模型和一组数据之间的平均距离.在您的情况下,b = 0,m是根频率,y代表给定值.最大的问题是没有明确给出自变量X. 我们对X的唯一了解是它的所有成员都必须是整数.

您的第一个任务是尝试确定这些自变量.我现在能想到的最好的方法是假定给定频率具有几乎连续的索引(x_1=x_0+n).所以B_0/B_1=(x_0)/(x_0+n)给出一个(希望)小整数n.然后,您可以利用以下事实:x_0 = n/(B_1-B_0)从n = 1开始,并保持棘轮直到k-rnd(k)在某个阈值内.拥有x_0(初始索引)后,您可以近似根频率(A = B_0/x_0).然后,您可以通过查找来估计其他索引x_n = rnd(B_n/A).此方法不是很健壮,如果数据中的错误很大,可能会失败.

如果您想要更好地近似根频率A,则可以使用线性回归来最小化线性模型的误差,因为您具有相应的因变量.最简单的方法是使用最小二乘拟合.Wolfram的Mathworld对这个问题进行了深入的数学处理,但是通过一些谷歌搜索可以找到一个相当简单的解释.

推荐阅读
Life一切安好
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有