我有许多有理数的集合,每个有的分子和分母存储为一个大的(数百或数千位)无符号整数。我希望能够有效地测试集合中任何给定的有理数a/b
是否等于集合中的任何其他有理数c/d
。
最直接的方法是测试是否a*d == b*c
,当然,但我想要比计算完整产品更有效率。
关于我的特定用例的一些注释:
我认为这在理论上可能是不可能的,但为了以防万一,将它扔到蜂巢头脑中。
答案 0 :(得分:1)
您可以通过比较位长度来过滤掉许多不相等的分数对。让 l ( a )= floor(log2( a ))+ 1 a 的位长。如果 a / b = c / d 而不是 l ( a )+ l ( d )= l ( c )+ l ( b'/ em>的)。
当您首次比较长度并比较产品时,只有长度总和相等时,才能将此用于加速。
答案 1 :(得分:1)
第二次尝试;)如果必须重复检查新数字以进行集合包含,则应将相对主要部分存储在有序集中。集合的比较函数应首先比较计数器,如果计数器相等,则应比较分母。比较可以在线性时间内完成,因此在 M 项目中查找有序集合中的元素需要 O ( N log M )步骤。降低分数成本 O ( N ²)。因此,测试一个包含的数字需要 O ( N ²+ N log M )步骤,并计算设置 O ( MN ²)。
编辑:您可以使用散列集来减少搜索 O 所需的步骤数而不是使用排序或树集( N ²+ N )= O ( N ²)。
答案 2 :(得分:0)
如果您已经预先计算了浮点近似值,那么在您的情况下这不会非常有用;它可能仍然会节省一些时间(或一些近似值)。
您检查a,b,c和d的整数值。
有理数是相同的意味着它们通过原点描述相同的行。
如果c> a,那么它也必须是d> b,否则我们会在右下方的灰色区域;如果c < a,相反,它必须是d&lt; b,或者我们会在左上方的灰色角落。灰色区域没有相等的可能性,如果数字是随机的(即不是浮点近似滤波的),我们将用N 2 bigint比较排除它们中的N / 2。
在剩余的50%中,我们可以通过注意到如果a>&gt;来排除一半。 b,则黑线位于第一和第三象限的平分线下方,并且必须是c> 1。 d,否则C / D将在平分线的另一侧;我们将处于最顶层的橙色部门,没有可能的平等。相同或者a&lt; b案例。因此,另外两个bigint比较将要检查的数量减少到原始的四分之一;那些可以用浮点近似,如果它们“几乎相等”,我们就处于需要其他技术的小红区。
你也可以通过观察任何k来扩展这个方法,对于a / b和c / d,a到k b的关系必须与c和k d之间的关系相同。平等如果k是2的整数幂,则允许几种可能的优化。
(当然,在某些时候,这个费用将超过a*d==b*c
测试的费用。