This expression is of type int, but is used here with a unit of type

I am trying to get the exact equivalent (not working) of this vb.net code in F #:

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

I wrote this:

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

but in the line "if ex = 0 then res" when res I got an error:
"This expression is of type int, but here it is used with a unit of type." I cannot understand why this gives me this error.
Edit: I also have a warning:
"This expression must be of type" unit ", but of type" int ".

With" if (ex% 2 = 1), then "

+3
source share
5 answers

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 *)

, , , 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

, , F # . exp >>> 1 int, , # -. , 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

, . 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

! Theres , , :)

+8

, , stat, , , "" , "else", .

:

let a = if true then 1;;

- int, .

:

let a = if true then 1 else 0;;

int .

+3

, , , , ().

let FastPow num exp =
   let mutable exp = exp
   let mutable res = 1
   let mutable n = num
   match exp with
   | O -> n <- num
   | _ when exp < 1 ->
      exp <- -exp
      n <- 1 / n
   | _ ->
       while exp > 1 do
          if (exp % 2 = 1) then 
             res <- res * n
          n <- n * n
          exp <- exp >>> 1
   res * n

, .

+1

, then - , . .

Edit

"" -

ex >>> 1

should be

ex <- ex >>> 1

:

let FastPow num exp =
    let calcExp num exp = 
        let mutable res = 1.0
        let mutable n   = num
        let mutable ex  = exp
        while ex > 1 do
            if ((ex % 2) = 1) then  
                res <- res * n
            n <- n * n
            ex <- ex >>> 1
        res * n

    match exp with
    | ex when ex = 0 -> 1.0
    | ex when ex < 0 -> calcExp (1.0/num) -exp
    | _ -> calcExp num exp

I just take out the calculation as a separate function, and in the end I check the arguments

0
source

Thanks for answers. This is the current non-functional version.

let FastPow num exp =
   let mutable ex = exp
   let mutable res = 1.0
   let mutable n = num
   if ex = 0 then 1.0
   else 
      if ex < 1 then
         ex <- -ex
         n <- 1.0 / n
      while ex > 1 do
         if (ex % 2 = 1) then res <- res * n
         n <- n * n
         ex <- ex >>> 1
      res * n

Now that I have a working version, I will try to make it more functional, but beyond the scope of this question. EDIT: I have the best results I expected, so I will post a recursive version optimized for speed (slightly faster than the iterative version and about 10% faster than the iterative version of C # (!!!) on my computer):

let rec loop res num exp =
   if exp = 0 then res
   elif (exp % 2) = 1 then loop (res * num) (num * num) (exp / 2)
   else loop res (num * num) (exp / 2)

let FP num exp =
   let n = if exp < 0 then 1.0 / num else num
   loop 1.0 n (Math.Abs(exp))
0
source

All Articles