composing floor and sqrt in haskell

后端 未结 2 1517
借酒劲吻你
借酒劲吻你 2021-01-06 02:41

I\'m just learning haskell (on my own, for fun) and I\'ve come up against a wall.

My Question:

How can I define a function

flrt = (floor . s         


        
2条回答
  •  一整个雨季
    2021-01-06 02:56

    As copumpkin remarked, it might actually be a bad idea to convert to floating point here, because this comes with loss of precision and therefore might, even with rounding, yield incorrect results for sufficiently large integer inputs.

    I assume all numbers you're dealing with will at least be small enough that there is some floating-point representation for them, e.g. all are < 10300. But, for instance

    Prelude> round(sqrt.fromInteger$10^60 :: Double) ^ 2
    1000000000000000039769249677312000395398304974095154031886336
    Prelude>  {-   and not   -}     10^60    {-  == (10^30)^2 == (sqrt$10^60) ^ 2  -}
    1000000000000000000000000000000000000000000000000000000000000
    

    Which is way off, in terms of absolute difference. Still it's certainly a rather good approximation relative to the numbers themselves, so you can use it as a quickly determined starting point for an algorithm to find the exact result. You can implement Newton/Raphson (in this case AKA Heron) with Integers:

    flrt :: Integer -> Integer  -- flrt x ≈ √x,  with  flrt x^2 ≤ x < flrt(x+1)^2
    flrt x = approx (round . (sqrt::Double->Double) . fromInteger $ x)
       where approx r
                | ctrl <= x, (r+1)^2 > x  = r
                | otherwise               = approx $ r - diff
              where ctrl = r^2
                    diff = (ctrl - x) // (2*r)    -- ∂/∂x x² = 2x
    
             a//b = a`div`b + if (a>0)==(b>0) then 1 else 0   -- always away from 0
    

    This now works as desired:

    *IntegerSqrt> (flrt $ 10^60) ^ 2
    1000000000000000000000000000000000000000000000000000000000000
    

    The division always away from 0 in the Newton-Raphson correction is here necessary to prevent getting stuck in an infinite recursion.

提交回复
热议问题