我试图在F#中获得此vb.net代码的完全等效(不起作用):
Function FastPow(ByVal num As Double, ByVal exp As Integer) As Double
Dim res As Double = 1
If exp < 1 Then
If exp = 0 Then Return res
exp = -exp
num = 1 / num
End If
Do While exp > 1
If exp Mod 2 = 1 Then
res = res * num
num = num * num
exp = exp >> 1
Loop
Return res * num
End Function
Run Code Online (Sandbox Code Playgroud)
我写了这个:
let FastPow num exp =
let mutable ex = exp
let mutable res = 1
let mutable n = num
if ex < 1 then
if ex = 0 then res
ex <- -ex
n <- 1 / n
while ex > 1 do
if (ex % 2 = 1) then
res <- res * n
n <- n * n
exp >>> 1
res * n
Run Code Online (Sandbox Code Playgroud)
但在"如果ex = 0然后res"行中我得到一个错误:
"这个表达式有类型int但是在这里用于类型单位".我无法理解为什么它会给我这个错误.
编辑:我实际上也收到了一个警告:
"这个表达式应该有'unit'类型,但是类型为'int'."
at"if(ex%2 = 1)then"
在F#中,函数的返回值是函数中计算的最后一个表达式.所以,让我们关注以下内容:
if ex < 1 then
if ex = 0 then res (* <--- this is not an early return *)
ex <- -ex (* <--- F# evaluates this code after the *)
n <- 1 / n (* if statement *)
Run Code Online (Sandbox Code Playgroud)
此外,if语句具有返回值,这也恰好是if语句中执行的最后一个值.如果if语句不是函数的返回值,则它应该具有返回类型unit.请注意,变量赋值的返回类型为unit.
我们需要重写您的代码以适应您的早期回报,因此我们可以这样做:
let FastPow2 num exp =
if exp = 0 then 1
else
let mutable ex = exp
let mutable res = 1
let mutable n = num
if ex < 1 then
ex <- -ex
n <- 1 / n
while ex > 1 do
if (ex % 2 = 1) then (* still have a bug here *)
res <- res * n
n <- n * n
exp >>> 1 (* <--- this is not a variable assignment *)
res * n
Run Code Online (Sandbox Code Playgroud)
我们仍然有一个错误,虽然我认为F#在错误的地方报告错误.表达式exp >>> 1返回一个int,它不分配任何变量,因此它不等同于你原来的C#代码.我认为你的意思是使用ex变量.我们可以按如下方式修复您的代码:
let FastPow2 num exp =
if exp = 0 then 1
else
let mutable ex = exp
let mutable res = 1
let mutable n = num
if ex < 1 then
ex <- -ex
n <- 1 / n
while ex > 1 do
if (ex % 2 = 1) then
res <- res * n
n <- n * n
ex <- ex >>> 1
res * n
Run Code Online (Sandbox Code Playgroud)
现在你的功能是固定的,但它真的很难看.让我们把它转换成更惯用的F#.您可以使用模式匹配替换if语句,并使用递归替换while循环:
let FastPow2 num exp =
match exp with
| 0 -> 1
| _ ->
let rec loop ex res n =
if ex > 1 then
let newRes = if ex % 2 = 1 then res * n else res
loop (ex >>> 1) newRes (n * n)
else res * n
let ex, n = if exp < 1 then (-exp, 1 / num) else (exp, num)
loop ex 1 n
Run Code Online (Sandbox Code Playgroud)
好多了!还有一些空间来美化这个功能,但你明白了:)