F # integer comparison

Given a list of ints from -273 to 5526, I want to print the nearest integer to zero. In case you have equality (n and -n), we should take n.

let temps = // this contains => 1 -2 -8 4 5

let (|Greater|_|) a b = if a > b then Some() else None
let (|Smaller|_|) a b = if a < b then Some() else None

let compareTemperatures a b = 
   let distanceA = abs a 
   let distanceB = abs b
   match distanceA with
   | Greater distanceB -> b
   | Smaller distanceB -> a
   | _ -> abs a

printfn "%i" (temps |> Seq.reduce compareTemperatures)

      

And that returns -8 instead of 1. It seems correct to me and I can't find the error, but I'm new to F #, so I could make the error anywhere and I can't see it :(

Thank you in advance

+3


source to share


3 answers


I think you got the wrong comparison - when you write:

match distanceA with
| Greater distanceB -> b
| Smaller distanceB -> a

      

It distanceA

is then passed as the second parameter to Greater

, and so you return b

(in the first case) in the case where it b

is farther from zero. The following would make it work:

match distanceA with
| Greater distanceB -> a
| Smaller distanceB -> b

      



However, using active templates to do this just makes the code unnecessarily complex (and makes it easy to introduce bugs like this). The following does the same and is easy to understand and also much simpler:

let compareTemperatures a b = 
  if abs a > abs b then b else a

temps |> Seq.reduce compareTemperatures

      

I think the lesson here is that pattern matching works really well for things like algebraic data types and parameter values, but it's not that useful for simple numerical comparisons where it if

works great!

+10


source


So you want to compare values ​​using the absolute value first, then the sign. Here's my one-liner:

temps |> Seq.minBy (fun x -> abs x, -sign x)

      



Test case (prints 2

):

let li = [-2; 2; -2; 3; -5]
li |> Seq.minBy (fun x -> abs x, -sign x) |> printfn "%d"

      

+2


source


This was supposed to be a comment on Thomas's answer, but I'm too stupid for a mobile app ...

How about if abs (2*a-1) > abs (2*b) then b else a

?

+1


source







All Articles