tags:

views:

46

answers:

2

I wrote a code:

let rec compareVs v1 v2 =
 if List.length v1 == 0 then
  true
 else
  ((match v1 with [] -> 0. | h::l -> h) == (match v2 with [] -> 0. | h::l -> h)) && 
  (compareVs(match v1 with [] -> [] | h::l -> l) (match v2 with [] -> [] | h::l -> l))

And ran it:

# compareVs [0.1;0.1] [0.1;0.1];;
- : bool = false

Can't seem to find the problem. Please help.

EDIT

The problem seams to be with float comparisons:

# 0.1 == 0.1;;
- : bool = false
# 1.0 == 1.0;;
- : bool = false

How else can we compare floats in ocaml?

+7  A: 

Use =, not ==.

Floats are reference types in ocaml and == checks reference equality. So 0.1 == 0.1 is false.

Generally, you almost always want to use =, not == to compare two values.

Note that aside from that, your function will return true for two lists of different size. Assuming that's not intended you should only return true when both lists are empty and false when one of them is empty and the other is not.

As a style note, using List.length to check whether a list is empty is usually a bad idea (for one thing it's O(n) even though it can be done in O(1) with pattern matching). Using pattern matching right at the beginning will also clean your code up a bit.

Like this:

let rec compareVs v1 v2 = match v1, v2 with
| [], []       -> true
| [], _
| _, []        -> false
| x::xs, y::ys -> x = y && compareVs xs ys

Oh and if this isn't just an exercise, note that you can just do v1 = v2 and don't actually need to write a function for this.

sepp2k
I didn't know we could use `,` with `match`. Could you suggest any site where I can find all kinds of usages or examples of `match` or pattern-matching in general with OCAML?
lalli
@lalli: `v1, v2` is a tuple and you can pattern match on tuples like on any other object. Also see [this page](http://caml.inria.fr/pub/docs/oreilly-book/html/book-ora016.html#toc14) for information about pattern matching.
sepp2k
+4  A: 

Sepp2k is correct, but as an additional discussion about comparing floats (which is often dangerous), the following functions have helped me:

This compares two floats with tolerance of epsilon and the syntax would be similar to other float functions. clearly extending >. and others is obvious.

let epsilon = 1.0e-10
let (=.) a b = (abs_float (a-.b)) < epsilon

If you are dealing with many extreme values of floats, you should look at the classify_float function in the pervasives module. I don't recall off the top of my head how NAN values are compared in the = function. You can independently experiment with this if you need to.

I had used this for awhile, but its tolerance was actually way to low for my usage (as in, a very small value for epsilon as above). This does not take into account what, NAN - NAN does. So, this might not be useful.

    let (=.) a b = match classify_float ( a -. b ) with
        | FP_infinite  | FP_nan | FP_normal -> false
        | FP_subnormal | FP_zero -> true
nlucaroni
good point, I forgot how I ran into trouble in c++ and java when comparing floats.
lalli