有效地检测有理数是相等的

时间:2016-11-21 19:31:01

标签: biginteger integer-arithmetic rational-numbers

我有许多有理数的集合,每个有的分子和分母存储为一个大的(数百或数千位)无符号整数。我希望能够有效地测试集合中任何给定的有理数a/b是否等于集合中的任何其他有理数c/d

最直接的方法是测试是否a*d == b*c,当然,但我想要比计算完整产品更有效率。

关于我的特定用例的一些注释:

  • 我正在测试的对很可能实际上是相等的(因为我已经预先计算并首先通过它们的浮点近似来比较它们),所以如果他们已经预先进行了早期外出不平等不会给我节省很多时间。
  • 我可以预先计算每个数字的额外数据,但每个数字只会用于少数比较,因此昂贵的预计算(例如素数因子分解)可能不值得。
  • 偶尔会出现假阴性,但误报不是。

我认为这在理论上可能是不可能的,但为了以防万一,将它扔到蜂巢头脑中。

3 个答案:

答案 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测试的费用。

numbers on the plane