我必须编写一个程序来查找具有属性的有理数。我写了代码来检查属性,但现在我不知道如何检查所有有理数。我试过
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;
}
但这有时只会起作用。我该如何解决这个问题?
答案 0 :(得分:10)
有理数是 countable ,这意味着它们可以与整数一一对应。如果你这样做,那么你就会得到解决方案。
不是给出一对一的通信,而是通过以下方式更简单地了解理性:
构造一个(可数)无限的(可数)无限矩阵Q
,以便Q_(i,j) = i/j
i
和j
的范围从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
的范围从i
到1
,但infinity
的范围仅为j
到1
。
如果您的i
功能需要相当长的时间,那么您可以先测试goodRat
和i
是互质的,如果没有跳过它们,也可以加快速度。
答案 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