为了账号安全,请及时绑定邮箱和手机立即绑定

圆整数解的算法?

圆整数解的算法?

MM们 2022-06-28 10:26:52
我正在尝试寻找方程的整数解:y^2 + x^2 = 2n^2如果我在 wolfram alpha 中搜索它,即使对于非常大的 n,它们几乎都可以立即找到。当我实施蛮力方法时,它非常慢:def psearch(n, count):    for x in range(0, n):        for y in range(0, n):            if x*x + y*y == 2*n**2:                print(x,y)                count += 1    return count所以我假设有一种更快的方法来获得上述方程的所有整数解。我怎样才能在 python 中做到这一点,以便它的运行时间要低得多?注意:我见过这个问题,但是它是关于在圆内找到格点,而不是圆方程的整数解。我也有兴趣找到具体的解决方案,而不仅仅是解决方案的数量。编辑:我仍在寻找更快的数量级的东西。这是一个例子: n=5 应该有 12 个整数解来找到应该在Wolfram alpha上搜索这个方程的那些解。编辑 2:@victor zen 对这个问题给出了惊人的答案。谁能想到进一步优化他的解决方案的方法?
查看完整描述

3 回答

?
慕森王

TA贡献1777条经验 获得超3个赞

在您的算法中,您正在搜索所有可能的 y 值。这是不必要的。这里的诀窍是要意识到


y^2 + x^2 = 2n^2

直接意味着


y^2 = 2n^2-x^2

所以这意味着你只需要检查 2n^2-x^2 是一个完美的正方形。你可以这样做


y2 = 2*n*n - x*x 

#check for perfect square

y = math.sqrt(y2)

if int(y + 0.5) ** 2 == y2:

    #We have a perfect square.

此外,在您的算法中,您只检查不超过 n 的 x 值。这是不正确的。由于 y^2 将始终为正数或零,我们可以通过将 y^2 设置为其最小值(即 0)来确定我们需要检查的最高 x 值。因此,我们需要检查所有满足的整数 x 值


x^2 <= 2n^2

这减少到


abs(x) <= sqrt(2)*n.

将此与仅检查上象限的优化相结合,您将获得优化的 psearch


def psearch(n):

    count = 0

    top = math.ceil(math.sqrt(2*n*n))

    for x in range(1, top):

        y2 = 2*n*n - x*x 

        #check for perfect square

        y = math.sqrt(y2)

        if int(y + 0.5) ** 2 == y2:

            count+=4

    return count


查看完整回答
反对 回复 2022-06-28
?
当年话下

TA贡献1890条经验 获得超9个赞

y>0在第一个八分圆内搜索就足够了x<y(四个解(±n, ±n)是显而易见的,并且通过对称性,一个解会(x, y)产生 8 个副本(±x, ±y), (±y, ±x))。


通过单调性,对于一个给定y的,至多有一个x。您可以通过逐步跟随圆弧,减少y然后调整来找到它x。如果您x²+y²≤2n²尽可能严格地保持条件,您会得到下面的代码,该代码已优化为仅使用初等整数算术(为了提高效率,2x使用 代替x)。


    x, y, d= 2 * n, 2 * n, 0

    while y > 0:

        y, d= y - 2, d - y + 1

        if d < 0:

            x, d= x + 2, d + x + 1

        if d == 0:

            print(x >> 1, '² + ', y >> 1, '² = 2.', n, '²', sep='')

以下是nbetween1和的所有解决方案100:


7² + 1² = 2.5²

14² + 2² = 2.10²

17² + 7² = 2.13²

21² + 3² = 2.15²

23² + 7² = 2.17²

28² + 4² = 2.20²

31² + 17² = 2.25²

35² + 5² = 2.25²

34² + 14² = 2.26²

41² + 1² = 2.29²

42² + 6² = 2.30²

46² + 14² = 2.34²

49² + 7² = 2.35²

47² + 23² = 2.37²

51² + 21² = 2.39²

56² + 8² = 2.40²

49² + 31² = 2.41²

63² + 9² = 2.45²

62² + 34² = 2.50²

70² + 10² = 2.50²

69² + 21² = 2.51²

68² + 28² = 2.52²

73² + 17² = 2.53²

77² + 11² = 2.55²

82² + 2² = 2.58²

84² + 12² = 2.60²

71² + 49² = 2.61²

79² + 47² = 2.65²

85² + 35² = 2.65²

89² + 23² = 2.65²

91² + 13² = 2.65²

92² + 28² = 2.68²

98² + 14² = 2.70²

103² + 7² = 2.73²

94² + 46² = 2.74²

93² + 51² = 2.75²

105² + 15² = 2.75²

102² + 42² = 2.78²

112² + 16² = 2.80²

98² + 62² = 2.82²

97² + 71² = 2.85²

113² + 41² = 2.85²

115² + 35² = 2.85²

119² + 17² = 2.85²

123² + 3² = 2.87²

119² + 41² = 2.89²

126² + 18² = 2.90²

119² + 49² = 2.91²

133² + 19² = 2.95²

137² + 7² = 2.97²

124² + 68² = 2.100²

140² + 20² = 2.100²


查看完整回答
反对 回复 2022-06-28
?
拉风的咖菲猫

TA贡献1995条经验 获得超2个赞

您可以通过仅考虑一个象限并乘以 4 来优化此算法。


import math

def psearch(n, count):

  for x in range( 0 , 2*n  + 1):

    ysquare = 2*(n**2) - x * x

    if (ysquare <0):

      break

    y = int(math.sqrt(ysquare))


    if ysquare ==  y * y :

      print(x,y)

      count+=1


  return count



print(psearch(13241324,0) * 4)

输出


(1269716, 18682964)

(1643084, 18653836)

(11027596, 15134644)

(12973876, 13503476)

(13241324, 13241324)

(13503476, 12973876)

(15134644, 11027596)

(18653836, 1643084)

(18682964, 1269716)

36


查看完整回答
反对 回复 2022-06-28
  • 3 回答
  • 0 关注
  • 151 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信