这是一个老问题,但我最近也在做同样的事情。正如你所说,你正在尝试做的就是高斯圆问题,这里有点描述
虽然我也很难理解这一切背后的严肃数学,但当不使用奇怪的外星符号时,它或多或少会变成这样:
1 + 4 * sum(i=0, r^2/4, r^2/(4*i+1) - r^2/(4*i+3))
在java中至少是:
int sum = 0;
for(int i = 0; i <= (radius*radius)/4; i++)
sum += (radius*radius)/(4*i+1) - (radius*radius)/(4*i+3);
sum = sum * 4 + 1;
我不知道为什么或如何工作,老实说我有点沮丧,我必须使用循环而不是单行来解决这个问题,因为这意味着性能是 O(r^2/4) 而不是 O (1)。
由于数学向导似乎不能比循环做得更好,我决定看看我是否可以将它降低到 O(r + 1) 的性能,我做到了。所以不要使用上面的,使用下面的。O(r^2/4) 很糟糕,即使我使用平方根也会变慢。
int sum = 0;
for(int x = 0; x <= radius; x++)
sum += Math.sqrt(radius * radius - x * x);
sum = sum * 4 + 1;
这段代码的作用是从中心向外沿一条正交线循环到边缘,并在每个点沿垂直方向添加从线到边缘的距离。最后它会有一个四分之一的点数,所以它将结果翻了两番并加了一个,因为还有中心点。我觉得 wolfram 方程做了类似的事情,因为它也乘以 4 并加一,但是 IDK 为什么它循环 r^2/4。
老实说,这些不是很好的解决方案,但它似乎是最好的解决方案。如果您正在调用一个定期执行此操作的函数,那么当新半径出现时,将结果保存在查找表中,而不是每次都进行完整计算。
它不是您问题的一部分,但它可能与某人有关,所以无论如何我都会添加它。我个人正在努力寻找一个圆圈内的所有点,其单元格定义为:
(centreX - cellX)^2 + (centreY - cellY)^2 <= radius^2 + radius
这使整个事情变得混乱,因为额外的+半径使这不完全符合勾股定理。额外的一点使圆圈在网格上看起来更具视觉吸引力,因为它们在正交边缘上没有那些小疙瘩。事实证明,是的,我的形状仍然是一个圆形,但是它使用 sqrt(r^2+r) 作为半径而不是 r,这显然有效,但不要问我如何。无论如何,这意味着对我来说,我的代码略有不同,看起来更像这样:
int sum = 0;
int compactR = ((radius * radius) + radius) //Small performance boost I suppose
for(int j = 0; j <= compactR / 4; j++)
sum += compactR / (4 * j + 1) - compactR / (4 * j + 3);
sum = sum * 4 + 1;