2017-05-05 55 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