F# Int 上的平方根
F# Square Root on Int
我正在用 F# 构建一个程序,我需要在其中计算整数值的平方根。
我搜索并找到了 none 函数,它允许在不使用强制转换的情况下执行此操作 int -> float
.
是否有一个函数可以在不进行不必要的强制转换的情况下计算整数的平方根?
如果您只想要一个接受整数和 returns 其平方根作为浮点数的函数,则使用 float
函数将整数转换为浮点数,然后调用 sqrt
是要走的路:
sqrt (float n)
原则上,F# 可以隐式允许这种转换,但我认为它不会这样做,因为它不清楚整数的平方根应该是什么(如评论中所讨论的)。在 C# 中,您可以编写 Math.Sqrt(n)
,但这是可行的,因为 C# 允许在程序的任何位置从 int
隐式转换为 float
。
如果整数 returns 整数需要平方根,则没有标准的方法(如评论中所述),因此由您来实现所需的功能。
我很难理解为什么对 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
我正在用 F# 构建一个程序,我需要在其中计算整数值的平方根。
我搜索并找到了 none 函数,它允许在不使用强制转换的情况下执行此操作 int -> float
.
是否有一个函数可以在不进行不必要的强制转换的情况下计算整数的平方根?
如果您只想要一个接受整数和 returns 其平方根作为浮点数的函数,则使用 float
函数将整数转换为浮点数,然后调用 sqrt
是要走的路:
sqrt (float n)
原则上,F# 可以隐式允许这种转换,但我认为它不会这样做,因为它不清楚整数的平方根应该是什么(如评论中所讨论的)。在 C# 中,您可以编写 Math.Sqrt(n)
,但这是可行的,因为 C# 允许在程序的任何位置从 int
隐式转换为 float
。
如果整数 returns 整数需要平方根,则没有标准的方法(如评论中所述),因此由您来实现所需的功能。
我很难理解为什么对 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