2017-05-05 56 views
1

我建设F#程序中,我需要做一个整数值的平方根。 我搜索了并且没有发现没有使用演员int -> float的功能。F#平方根的诠释

是否有一个功能,允许做一个整数的平方根没有不必要的投?

+2

回退一点:如何定义一个整数的平方根? 8的平方根是多少?应该是2(2.828的底线)还是3(2.828的底线)还是3(2.828的“数学积分”)?它没有很好的定义,并且根据您的应用程序,您可能需要选择其中一个选项。 –

+2

安东的问题是一个很好的问题。我还有一个问题:**为什么**你需要这个? (或者为什么你认为你需要这个?)因为我发现,当有人问X没有解释他们为什么需要它,X是难以/不可能的(例如,在整数平方根函数),它通常原来他们真的试图做Y,他们认为X是做Y的唯一方式。那么我们可以说:“好吧,还有另一种方式去做Y而不做X,它看起来像这样,”这通常是比困难/不可能的X更好的解决方案。 – rmunn

+0

我想从字面上看,对于某些测试,找到int类型的平方根。 – eisterman

回答

3

如果你只是想要一个函数,它接受一个整数并返回其平方根作为浮点,然后使用float功能为int转换为浮点,然后调用sqrt是要走的路:

sqrt (float n) 

原则,F#可能允许这种转换含蓄,但我觉得,因为它不这样做,因为什么样的整数的平方根应(如在评论中讨论),目前尚不清楚。在C#中,你可以写Math.Sqrt(n),但这个工程,因为C#允许从intfloat在你的程序的任何地方隐式转换。

如果你想有一个平方根如果返回一个整数整数,再有就是这样做的(如在评论中讨论)的标准方式,所以它是由你来实现你需要的功能。

0

我很难理解为什么限制为int输入,但如果这是重要的,可以采用除法算法分割&。在任何带有硬件浮点的CPU架构上,这比sqrt (float n)慢很多。

let isqrt n = 
    let rec loop b e = 
    let i = (b + e) >>> 1 
    let i2 = i*i 
    if i2 = n then 
     i 
    else 
     let nb, ne = 
     if i2 > n then 
      b, i 
     else 
      i, e 
     if nb = b && ne = e then 
     // Check i - 1 and i + 1 to see if either is a better fit than i 
     let imin = i - 1 
     let imax = i + 1 
     let i2min = imin*imin 
     let i2max = imax*imax 
     let d  = n - i2 |> abs 
     let dmin = n - i2min |> abs 
     let dmax = n - i2max |> abs 
     if d < dmin && d < dmax then 
      i 
     elif dmin < dmax then 
      imin 
     else 
      imax 

     else 
     loop nb ne 
    loop 1 n 

open FsCheck 

let isqrtProperty n = 
    n > 1 ==> fun() -> 
    let r  = isqrt n 
    let rmin = r - 1 
    let rmax = r + 1 

    let r2 = r*r 
    let rmin2 = rmin*rmin 
    let rmax2 = rmax*rmax 

    let d  = n - r2  |> abs 
    let dmin = n - rmin2 |> abs 
    let dmax = n - rmax2 |> abs 

    r >= 0 && d <= dmin && d <= dmax 

[<EntryPoint>] 
let main argv = 
    let config = { Config.Quick with MaxTest = 10000; MaxFail = 100000 } 
    Check.One ("isqrt property", config, isqrtProperty) 
    0