用财产找一个有理数

时间:2011-06-16 01:49:30

标签: algorithm rational-numbers

我必须编写一个程序来查找具有属性的有理数。我写了代码来检查属性,但现在我不知道如何检查所有有理数。我试过

float rat;
for (int i=1 ; i ; ++i) {
  for (int j=1 ; j ; ++j) {
    rat = (float)i/(float)j;
    if goodRat(rat) then return rat;
  }
}

但它永远不会结束!它错过了太多。那么我试过这个

float rat;
while {
  int i = random(1000) + 1;
  int j = random(1000) + 1;
  rat = (float)i/(float)j;
  if goodRat(rat) 
      return rat;
}

但这有时只会起作用。我该如何解决这个问题?

3 个答案:

答案 0 :(得分:10)

有理数是 countable ,这意味着它们可以与整数一一对应。如果你这样做,那么你就会得到解决方案。

不是给出一对一的通信,而是通过以下方式更简单地了解理性:

构造一个(可数)无限的(可数)无限矩阵Q,以便Q_(i,j) = i/j ij的范围从1到{{1} }}。矩阵看起来像这样:

infinity

当然,有很多重复(整个对角线都是1!),但我的目的是为了简化速度。

你要做的就是走下无限的列,这样你就会错过很多数字。相反,你应该走有限的反对角线。也就是说,按以下顺序获取元素

 1  1/2 1/3 1/4 1/5 . . .
2/1 2/2 2/3 2/4 2/5 . . .
3/1 3/2 3/3 3/4 3/5 . . . 
4/1 4/2 4/3 4/4 4/5 . . .
5/1 5/2 5/3 5/4 5/5 . . .
 .   .   .   .   .
 .   .   .   .   .
 .   .   .   .   .

所以你会得到 1 3 6 10 15 . 2 5 9 14 . . 4 8 13 . . . 7 12 . . . 11 . . . . . . . . . 。此外,您知道在步骤1, 2/1, 1/2, 3/1, 2/2, 1/3, 4/1, 3/2, 2/3, 1/4, ...会遇到r/s,因此在有限时间内会遇到任何给定的有理数。

对此进行编码的一种方法是让(r+s)(r+s-1)/2 + s成为行索引(外部i循环)并让for成为列索引(内部j循环)。然后for的范围从i1,但infinity的范围仅为j1

如果您的i功能需要相当长的时间,那么您可以先测试goodRati是互质的,如果没有跳过它们,也可以加快速度。

答案 1 :(得分:4)

Stern–Brocot tree是一种系统地生成所有有理数而无需重复的方法。请参阅https://math.stackexchange.com/questions/7643/produce-an-explicit-bijection-between-rationals-and-naturals上的其他人。

答案 2 :(得分:0)

首先,关于你的第一次尝试:

float rat;
for (int i=1 ; i ; ++i) {
    // the loop for the first won't be reached
  for (int j=1 ; j ; ++j) {
  // this loop will never end, it will either loop for ever or return something like (floag)1/(float)j
    rat = (float)i/(float)j;
    if goodRat(rat) then return rat;
  }
}

我的建议是,明确你的目的,也许你可以参考http://en.wikipedia.org/wiki/Stern-Brocot_tree