Optimization 类型球拍的优化。。。这是不是太过分了?

Optimization 类型球拍的优化。。。这是不是太过分了?,optimization,integer,racket,typed-racket,Optimization,Integer,Racket,Typed Racket,关于打字/拍子的问题。我目前正在努力学习如何更好地学习球拍。有些是非常缓慢的,特别是在处理素数和因子时。所以对于一些问题,我试着制作一个打字版/拍子版,但我发现速度没有提高,恰恰相反。(我试图通过使用非常大的数字来最小化开销的影响,计算时间大约为10秒。) 我从Racket文档中知道最好的优化会发生。所以是的,我试着把处理整数的问题写成浮点形式。例如,使用整数和人工将整数变为浮点数。我必须使用技巧:检查两个数字之间的相等实际上意味着检查它们是否“足够接近”,就像在这个函数中检查x是否可以除以y:

关于打字/拍子的问题。我目前正在努力学习如何更好地学习球拍。有些是非常缓慢的,特别是在处理素数和因子时。所以对于一些问题,我试着制作一个打字版/拍子版,但我发现速度没有提高,恰恰相反。(我试图通过使用非常大的数字来最小化开销的影响,计算时间大约为10秒。)

我从Racket文档中知道最好的优化会发生。所以是的,我试着把处理整数的问题写成浮点形式。例如,使用整数和人工将整数变为浮点数。我必须使用技巧:检查两个数字之间的相等实际上意味着检查它们是否“足够接近”,就像在这个函数中检查x是否可以除以y:

(: divide? (-> Flonum Flonum Boolean))
(define (divide? x y)
  (let ([r (/ x y)])
    (< (- r (floor r)) 1e-6)))
(:除?(>Flonum-Flonum-Boolean))
(定义(除以?x y)
(让([r(/x y)])
(<(-r(楼层r))1e-6)
它工作(嗯…解决方案是正确的),我有30%-40%的速度提高


这是否可以接受?人们在现实生活中真的这么做了吗?如果不是,那么在使用整数时,优化类型化解决方案的最佳方法是什么?或者,在处理整数时,是否应该完全放弃类型化/racket,而保留用于浮点计算的问题?

在大多数情况下,解决方案是使用更好的算法,而不是转换为类型化racket

由于Project Euler中的大多数问题都与整数有关,以下是一些提示和技巧:

  • 除法运算符
    /
    需要计算分母和分子之间的最大公除法,以抵消公因数。如果您只想知道一个数字是否除以另一个数字,那么这就使得
    /
    成为一个错误的选择。使用
    (=(余数n m)0)
    检查
    m
    是否除以
    n
    。另外:当您知道除法的余数为零时,请使用
    /
    随机数

  • 使用备忘录避免重新计算。即,使用向量存储已计算的结果。例如:

  • 首先实现一个简单的算法。然后考虑如何减少案件数量。经验法则:如果你能将案件数量减少到100-1000万,暴力效果最好

  • 要减少案例数量,请查找搜索空间的参数化。示例:如果需要查找毕达哥拉斯三元组:在数字m和n上循环,然后计算
    a=m^2-n^2
    b=2mn
    ,以及
    c=m^2+n^2
    。这将比在a、b和c上循环快,跳过a^2+b^2=c^2不正确的三元组

  • 数学/数论
    的源代码中寻找技巧和窍门


  • 我不想成为一个真正的答案,因为我不能提供任何一般性的提示,苏加德还没有发布,但因为我最近做了“友好的数字” “问题21”,我想还是把我的解决方案留在这里吧(遗憾的是,在Euler上发布的Lisp解决方案不多…)


    当处理除数时,通常可以停在n的平方根处,就像这里的
    divSum
    一样。当你找到一对友好的组合时,你也可以同时将这两个组合加到和中,这样你就不用在我的代码中计算
    (divSum b)

    注意:对于平方根,请考虑使用
    整数sqrt
    而不是
    sqrt
    (define (divSum n)
      (define (aux i sum)
        (if (> (sqr i) n)
            (if (= (sqr (sub1 i)) n)  ; final check if n is a perfect square
                (- sum (sub1 i))
                sum)
            (aux (add1 i) (if (= (modulo n i) 0)
                              (+ sum i (/ n i))
                              sum))))
      (aux 2 1))
    
    
    (define (amicableSum n)
      (define (aux a sum)
        (if (>= a n)
            sum
            (let ([b (divSum a)])
              (aux (add1 a)
                   (if (and (> b a) (= (divSum b) a))
                       (+ sum a b)
                       sum)))))
      (aux 2 0))
    
    > (time (amicableSum 10000))
    cpu time: 47 real time: 46 gc time: 0