Convert float to float option - ocaml

How can I convert float to float option. Here is the function:
let variance (list_ : float list) : float option =
if List.length list_ < 2 then None
else begin
let average tmp_list = List.fold_left(+.) 0. tmp_list /. float(List.length tmp_list) in
let square value = value *. value in
let rec sum tmp_list =
match tmp_list with
| [] -> 0.0
| head::tail -> square (head -. average tmp_list) +. sum tail
in Some (sum list_ /. float(List.length list_))
end
I need sum list_ /. float(List.length list_) to return float option instead of float and I don't know how to do it. I thought if I return float in a float option function it would automatically return float option but I get the following error:
Error: This expression has type float but an expression was expected
of type float option
I have tried wrapping it around Some and failed. Can't seem to find anything on the internet.
EDIT: Added the full code

Your code runs, it just gives the wrong answer. That's because you sum function is incorrect : you should always use the average of the whole list, whereas you use the average from the current element onwards.
let variance l =
let sum l = List.fold_left (+.) 0. l in
let average l =
match List.length l with
0 -> None
| n -> Some (sum l /. float_of_int n) in
match average l with
None -> None
| Some m -> average (List.map (fun x -> (x -. m)**2.) l)

Related

How to compute the average of a list of a special record in OCaml?

Lets say we have a record which defines students:
type student = {
name : string;
age : int;
grades : (float) list;
}
And safe them in a list like this:
let studentlist = [ {name="alex"; age=7; grades=[1.;2.;3.]} ;
{name="bianca"; age=6; grades=[1.;1.;2.]} ];;
My aim is to compute the grade average of a special student which I choose per age, I select the student with the function search:
let search a lst = List.find( fun {age;_} -> a = age)lst
And compute the average with the help-functions , named sum, length and finally avr :
let rec sum lst =
match lst with
| [] -> 0.0
| h :: t -> h +. sum t
let length lst = float_of_int (List.length lst);;
let avr lst = sum lst /. length lst;;
I don't know how to combine those functions to compute the average properly!
Most of what you've done seems to work. For instance, search works.
utop # search 7 studentlist;;
- : student = {name = "alex"; age = 7; grades = [1.; 2.; 3.]}
If you want to access the grades field of that record, use . for record access.
utop # (search 7 studentlist).grades;;
- : float list = [1.; 2.; 3.]
Now that you have a list of float values, finding the sum or average of them should be easy by passing that value as an argument to the relevant function you've already defined.
Bear in mind that when you use List.find in search, if you search for an age that is not present, you will get a Not_found exception that you will want to handle.
As an aside, note that your avr function iterates over the list twice. Once to compute the sum, and ocne to compute the length.
It is possible to computer the sum, the length, and the average in a single pass. We can use a fold to do this. First off, we can define a basic left fold:
let rec foldl f init lst =
match lst with
| [] -> init
| x::xs -> foldl f (f init x) xs
Consider using this to compute the length of a list:
foldl (fun i _ -> i + 1) 0 [1.; 2.; 3.]
When evaluated:
foldl (fun i _ -> i + 1) 0 [1.; 2.; 3.]
foldl (fun i _ -> i + 1) (0 + 1) [2.; 3.]
foldl (fun i _ -> i + 1) (1 + 1) [3.]
foldl (fun i _ -> i + 1) (2 + 1) []
3
But we can pass a tuple of values to foldl, building up the length, sum, and average as we go.
utop # let (len, sum, avg) = foldl
(fun (len, sum, avg) x ->
let sum = sum +. x in
let len = len + 1 in
let flen = float_of_int len in
(len, sum, sum /. flen))
(0, 0., 0.)
[1.; 2.; 3.];;
val len : int = 3
val sum : float = 6.
val avg : float = 2.

f# concatenate list of objects

type Googol = {
number : float
power : float
result : float
}
let generatePowers (n:float) : list<Googol> =
let rec powerInner (n:float) (p:float) (acc : list<Googol>) =
match n with
| p when p <= 1.0 -> acc
| p when p > 1.0 -> powerInner n (p-1.0) ([{ number=n; power=p; result=n**p}]#acc)
let rec numberInner (n:float) (acc : list<Googol>) =
match n with
| n when n <=1.0 -> acc
| n when n >1.0 -> numberInner (n-1.0) ((powerInner n [])#acc)
numberInner n []
ProjectEuler.fsx(311,50): error FS0001: This expression was expected to have type
'Googol list'
but here has type
'Googol list -> Googol list'
I am trying to solve this problem -> https://projecteuler.net/problem=56 | but for this I need to generate powers below n < 100. When I try to concatenate [{ number=n; power=p; result=n**p}]#acc
these lists I get the error above. Explain please why error says 'Googol list -> Googol list' is in the function, does I plug a function as a parameter to the function or I plug the actual list when just after concatenation. Is # a function?
This looks like homework or practice, so first I'll give some hints to move on. Finally I'll show a version that seems to work, and then tell how I would approach the problem.
The task is to find the number a ** b, for a and b less than 100, that has the highest sum of its own digits.
The first problem is that float won't give us all the digits of a ** b, so that type is useless to solve the problem. To fix that, we turn to the BigInteger type, and the BigInteger.Pow function. Then we get a 1 followed by 200 zeroes if we run the following snippet, just like it says in the problem description.
let x: bigint = BigInteger.Pow (100I, 100)
let x: string = string x
printfn "s=%s" x
To get useful results, change the Googol type so that it uses bigint, except for power that should be an int.
Why are the functions powerInner and numberInner inside the function generatePowers? This doesn't seem to have a specific purpose, so I suggest moving them out to make this clearer.
The function powerInner do a match on n, but then goes on to name the results p, which shadows the p parameter so that it is unused. Ok, the intention here is probably to match on p rather than n, so just fix that, and then the shadowing of the p parameter is perfectly fine.
The tests first on <= 1 and then on > 1 causes incomplete matches. If the first line checks that the number is less or equal to one, then it must the greater than one in the next line. So just use n -> without the when to fix that. I also suspect you want to test <= 0 instead of 1.
This
[{ number=n; power=p; result=n**p}]#acc
can be just
{ number=n; power=p; result=n**p } :: acc
and here
(powerInner n [])
I suspect you just need a starting value for the power, which would be 99
(powerInner n 99 [])
SPOILER WARNING
After a bit of tinkering, this is what I ended up with, and it seems to print out a useful list of numbers. Note that in order to not run through all 99 by 99 results with printouts, I've used low starting numbers 3 and 5 for the countdowns here, so we get some simple printout we can study for analysis.
type Googol = { number: bigint; power: int; result: bigint }
let rec powerInner (n: bigint) (p: int) (acc: Googol list) =
match p with
| p when p <= 0 -> acc
| p ->
let newNumber = { number = n; power = p; result = n ** p }
printfn "newNumber=%0A" newNumber
powerInner n (p - 1) (newNumber :: acc)
let rec numberInner (n: bigint) (acc: Googol list) =
match n with
| n when n <= 0I -> acc
| n -> numberInner (n - 1I) ((powerInner n 5 []) # acc)
let generatePowers (n: bigint) : Googol list =
numberInner n []
let powers = generatePowers 3I
I'm not sure if this solution is correct. I'd do it differently anyway.
I would simply loop through a and b in two loops, one inside the other. For each a ** b I would convert the result to a string, and then sum the digits of the string. Then I'd simply use a mutable to hold on to whichever result is the highest. The same could be achieved in a more functional way with one of those fancy List functions.
You're missing a parameter here:
| n when n >1.0 -> numberInner (n-1.0) ((powerInner n [])#acc)
^^^^^^^^^^^^^^^
here
powerInner is defined with three parameters, but you're only passing two.
In F# it is not technically illegal to pass fewer parameters than defined. If you do that, the result will be a function that "expects" the remaining parameters. For example:
let f : int -> int -> string
let x = f 42
// Here, x : int -> string
let y = x 5
// Here, y : string
So in your case omitting the last parameter makes the resulting type Googol list -> Googol list, which then turns out to be incompatible with the type Googol list expected by operator #. Which is what the compiler is telling you in the error message.

I'm in trouble with making a differentiating function in OCaml (not about syntax issue)

type aexp =
| Const of int
| Var of string
| Power of string * int
| Times of aexp list
| Sum of aexp list
let rec diff : aexp * string -> aexp
= fun (exp, var) ->
match exp with
|Const a -> Const 0
|Var x -> if x = var then Const 1 else Var x
|Power (s, i) ->
if s = var then Times [Const i; Power (s, i - 1)] else Power (s, i)
|Times l ->
begin match l with
|h::t -> Sum ((Times (diff (h, var) :: t)) # (h :: Times (diff (Times t, var))))
end
|Sum l ->
begin match l with
|h::t -> Sum (diff(h, var) :: diff(t, var))
end
This code is expected to work as follows :
diff (Times[Const 2; Var "x"], "x")
then the output must be
Times[Const 2; Const 1]
because if we differentiate 2x, the result is 2
but the error occurs and it says :
File "", line 18, characters 20-25:
Error: This variant expression is expected to have type 'a list
The constructor Times does not belong to type list
Why this error happens? I think there are some spots that are wrong, but I can't find any logical incorrectness.
Some mathematical notes:
The derivative of a variable not x by a variable x is zero, not the original variable.
The same for a power of a variable not x, it is also a constant relative to x.
Why only powers of variables, (a+b)^i is not possible. The more general case is as easy as the special case.
For the derivative of the product consider three factors and include that the first recursive step splits u and v*w
(u*v*w)' = u'*v*w + u*(v'*w+v*w')
In a prefix notation this can be written as
diff(*[u,v,w])=+[*[u',v,w],*[u,+[*[v',w],*[v,w']]]]
which should be reflected in something like
|h::t -> Sum ((Times (diff (h, var) :: t)) # (Times (h :: (diff (Times t, var)))))
As two-element lists, could this also be written as
|h::t -> Sum ( Times (diff (h, var) :: t) , Times (h ,diff (Times t, var)))
Let's look at this expression:
h :: Times (diff (Times t, var))
for simplicity let's substitute diff (Times t, var), with the dtdv, so that we have
h :: Times dtdv
The :: infix constructor requires that an expression to the left of its should have type 'a, while an expression to the right should have a value of type 'a list. An expression to the right is Times dtdv, and constructor Times creates values of type aexp, not values of type list.
Btw, you also have two more errors and two more warnings. These errors are of the same kind, i.e., you're trying to apply a value of type aexp in a place where a list is required, i.e., here:
Times (diff (h, var) :: t)) # (h :: Times (diff (Times t, var))
Let's simplify it again
Times (dhv::t) # rest
The # operator expects lists on both sides, and Times something, as we already discussed, are not a list.
It looks like, that it is hard for you to pass through the big amount of parenthesis and precedence rules. I hate parenthesis. So, I always try to use let ... in sparingly, e.g., let's rewrite the following expression:
Sum ((Times (diff (h, var) :: t)) # (h :: Times (diff (Times t, var))))
With a more verbose, but understanble version:
let h' = diff (h,var) in
let t' = diff (Times t,var) in
let lhs = Times (h'::t) in
let rhs = h :: Times t' in
Sum (lhs#rhs)
Now it is much more readable, and you can tackle with all problems one by one.
Also, I'm would suggest not to try to solve everything in a big fat function, but instead separate things into smaller functions that are easier to handle, this will also solve you a problem with the match inside a match, e.g., the following function has a structure that is much easier to understand:
let rec diff : aexp * string -> aexp = fun (exp, var) ->
match exp with
|Const a -> Const 0
|Var x -> if x = var then Const 1 else Var x
|Power (s, i) -> diff_power s i
|Times l -> diff_times l
|Sum l -> diff_sum l
and diff_power s i =
if s = var then Times [Const i; Power (s, i - 1)] else Power (s, i)
and diff_times l = match l with
|h::t -> Sum ((Times (diff (h, var) :: t)) # (h :: Times (diff (Times t, var))))
and diff_sum l = match l with
|h::t -> Sum (diff(h, var) :: diff(t, var))

String to float in OCaml: over and under approximation

Given a string of a (possibly big) integer, I need to convert it to floating-point numbers, in OCaml. The problem is that the conversion is not always exact due to rounding errors. For example, float_of_string "61035156250000000000" would return 61035156249999998976. How can I under-approximate and over-approximate the number to get an interval [a, b] where
a is the largest representable floating-point number such that a <= 61035156250000000000
b is the smallest representable floating-point number such that b >= 61035156250000000000?
You have to get an approximate value, bracket the accurate value (which may not be representable as float) and binary search. Here is a short program I wrote to do this:
let num_of_float x =
let two = Num.num_of_int 2 in
let rec expand x =
let fr, wh = modf x in
Num.add_num (Num.num_of_int (int_of_float wh))
(if fr = 0.0 then Num.num_of_int 0 else
Num.div_num (expand (2.0*.fr)) two) in
let fl, ex = frexp x in
if ex <> 0 then Num.mult_num (expand fl) (Num.power_num two (Num.num_of_int ex))
else
expand x
let bracket str =
let x = Num.num_of_string str in
let rec binsearch a b =
let t = (b-.a)*.0.5 +. a in
if (t = a) || (t = b) then (a,b) else
match Num.compare_num x (num_of_float t) with
| -1 -> binsearch a t
| 0 -> (t,t)
| 1 -> binsearch t b
| _ -> failwith "compare_num" in
let near = Num.float_of_num x in
let delta = 1.0 +. (4.0*.epsilon_float) in
binsearch (near/.delta) (near*.delta)
let () =
let l,r = bracket "61035156250000000000" in
Printf.printf "[%.16g = %s, %.16g = %s]\n"
l (Num.string_of_num (num_of_float l)) r (Num.string_of_num (num_of_float r))
Compile with the Num module to get this output:
[6.103515625e+19 = 61035156249999998976, 6.103515625000001e+19 = 61035156250000007168]
You will need to tweak the delta value and check for NaNs, infinity and conversion errors to get a robust method.
This has to due with the fact that float numbers are stored as A_ * pow(2,B_).
What you need is a BigInt
http://caml.inria.fr/pub/docs/manual-ocaml/libref/Big_int.html

How to sum a list of float numbers in OCaml

I am puzzled with my code:
let sum l = match l with
| [] -> 0.0
| h::t -> h +. (sum t);;
It should give me the sum of the numbers in the list. However when I check the code, I found the second code crashes when I use a list of length greater than or equal to 7. Here is the code:
# sum [0.;1.;2.;3.;4.;5.;]
- : float = 15.
# sum [0.;1.;2.;3.;4.;5.;6.]
- : float = 21.
# sum [0.;1.;2.;3.;4.;5.;6.;7.]
- : float = 21.
I am really confused because a modification of it, which operates on int, turned out to be normal:
let rec sumf l = match l with
| []-> 0.0
| h::t-> (float_of_int h) +. sumf t;;
and I do not know what is the essential difference between the two aside from I cast int into float in the second code.
let sum l=
match l with
[]->0.0
|h::t-> h+. (sum t);;
Since you didn't use the rec keyword here, the call to sum in the last line is a call to a sum function that you defined beforehand. Apparently that sum function was buggy.
I don't understand why your code crashes. When I try your sum function with rec keyword, I don't have any problem, otherwise you can't call recursively the sum function.
let rec sum l =
match l with
[] -> 0.
| h :: t -> h +. (sum t);;
You can also use the fold_left function in module List:
let sum l = List.fold_left (+.) 0. l;;