簡體   English   中英

Int上的F#平方根

[英]F# Square Root on Int

我在F#中構建一個程序,我需要在其中執行整數值的平方根。 我搜索並發現沒有允許在不使用cast int -> float情況下執行此操作的函數。

是否有一個函數允許在沒有不必要的強制轉換的情況下生成整數的平方根?

如果你只是想要一個取整數並將其平方根作為浮點返回的函數,那么使用float函數將int轉換為浮點然后調用sqrt是要走的路:

sqrt (float n)

原則上,F#可以隱式允許這種轉換,但我認為它不會這樣做,因為它不清楚整數的平方根應該是什么(如注釋中所討論的)。 在C#中,您可以編寫Math.Sqrt(n) ,但這是有效的,因為C#允許在程序中的任何位置從intfloat進行隱式轉換。

如果你想要一個平方根,如果整數返回整數,那么沒有標准的方法(如評論中所討論的那樣),所以由你來實現你需要的功能。

我很難理解為什么對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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM