我正在尝试在各种3D椭圆内找到所有整数点。
我希望我的程序可以接受一个整数N,并计算形如ax^2 + by^2 + cz^2 = n的椭圆内的所有格点数量,其中a、b、c是固定整数,n介于1和N之间。该程序应返回N个元组,形式为(n,numlatticePointsWithinEllipse n)。
我目前是通过计算椭圆ax^2 + by^2 + cz^2 = m上的点数,其中m介于0和n之间,并对m求和来实现的。我最初只考虑x、y和z都为正数的情况,然后通过稍后排列它们的符号来添加负数。
理想情况下,我希望在几个小时内达到N = 1,000,000+的数字。
以x ^ 2 + y ^ 2 + 3z ^ 2 = N为具体例子,这是我目前使用的Haskell代码:
我已经使用编译器进行了编译。
我希望我的程序可以接受一个整数N,并计算形如ax^2 + by^2 + cz^2 = n的椭圆内的所有格点数量,其中a、b、c是固定整数,n介于1和N之间。该程序应返回N个元组,形式为(n,numlatticePointsWithinEllipse n)。
我目前是通过计算椭圆ax^2 + by^2 + cz^2 = m上的点数,其中m介于0和n之间,并对m求和来实现的。我最初只考虑x、y和z都为正数的情况,然后通过稍后排列它们的符号来添加负数。
理想情况下,我希望在几个小时内达到N = 1,000,000+的数字。
以x ^ 2 + y ^ 2 + 3z ^ 2 = N为具体例子,这是我目前使用的Haskell代码:
import System.Environment
isqrt :: Int -> Int
isqrt 0 = 0
isqrt 1 = 1
isqrt n = head $ dropWhile (\x -> x*x > n) $ iterate (\x -> (x + n `div` x) `div` 2) (n `div` 2)
latticePointsWithoutNegatives :: Int -> [[Int]]
latticePointsWithoutNegatives 0 = [[0,0,0]]
latticePointsWithoutNegatives n = [[x,y,z] | x<-[0.. isqrt n], y<- [0.. isqrt (n - x^2)], z<-[max 0 (isqrt ((n-x^2 -y^2) `div` 3))], x^2 +y^2 + z^2 ==n]
latticePoints :: Int -> [[Int]]
latticePoints n = [ zipWith (*) [x1,x2,x3] y | [x1,x2,x3] <- (latticePointsWithoutNegatives n), y <- [[a,b,c] | a <- (if x1 == 0 then [0] else [-1,1]), b<-(if x2 == 0 then [0] else [-1,1]), c<-(if x3 == 0 then [0] else [-1,1])]]
latticePointsUpTo :: Int -> Int
latticePointsUpTo n = sum [length (latticePoints x) | x<-[0..n]]
listResults :: Int -> [(Int, Int)]
listResults n = [(x, latticePointsUpTo x) | x<- [1..n]]
main = do
args <- getArgs
let cleanArgs = read (head args)
print (listResults cleanArgs)
我已经使用编译器进行了编译。
ghc -O2 latticePointsTest
但是使用PowerShell的"Measure-Command"命令,我得到了以下结果:
Measure-Command{./latticePointsTest 10}
TotalMilliseconds : 12.0901
Measure-Command{./latticePointsTest 100}
TotalMilliseconds : 12.0901
Measure-Command{./latticePointsTest 1000}
TotalMilliseconds : 31120.4503
如果我们再向上推一个数量级,就会进入几天的时间尺度,而不是几小时或几分钟。
我的算法有什么根本性问题吗?是什么核心原因导致我的代码不适用于大规模数据?任何指导都将不胜感激。我可能还想在“latticePoints”和“latticePointsUpTo”之间处理数据,因此不能完全依赖巧妙的数论计数技巧-我需要保留底层元组。
isqrt
定义为floor . sqrt . fromIntegral
呢? - jub0bsarithmoi
包 中的工具。 - recursion.ninjaax^2 + by^2 + cz^2 = n/q
,那么你知道qax^2 + qby^2 + qcz^2 = n
存在。这种多重记忆技术将适用于集合[2..sqrt n]
中的所有数字q
。高效的优化可能会退化为应用数论定理。这可能会在 math.SE 上得到更好的接受。 - recursion.ninjafloor
和sqrt
的评论。 - ErikR