I am trying to calculate the square root of a number by Ocaml, this is my code :
let isclose x y = abs_float(x -. y)<0.001;;
let average x y = (0.5*.x)+.(0.5*.y);;
let rec guess x y = if isclose y (x /. y) then y else guess x (average y x/.y);;
let sqr x = guess x 1.;;
then, typing
sqr 1.;;
gives 1 as expected, but typing
sqr 2.;;
lasts undefinitely.
Can one help with my error (I tested the algo in Python and it works as expected).
Thanks for help
You want this:
let rec guess x y =
if isclose y (x /. y) then y else guess x (average y (x/.y))
Note the extra parentheses.
The meaning of
average y x /. y
is
(average y x) /. y
Whereas you want:
average y (x /. y)
Related
I have the following code where I define a composite function f(r(x,y),theta(x,y)), and I'm trying to simplify f.diff(x) assuming that I know an expression for f.diff(r):
x, y = sp.symbols("x y", real=True)
r = sp.Function('r')(x, y)
phi = sp.Function('phi')(x, y)
f = sp.Function('f')(r, phi)
df_dr = sp.Function('df_dr')(r, phi)
df_phi = sp.Function('df_phi')(r, phi)
Next, I compute the derivatives of f(r,phi) with respect to x:
f.diff(x)
And I get the following:
Derivative(phi(x, y), x)*Subs(Derivative(f(r(x, y), _xi_2), _xi_2), _xi_2, phi(x, y)) + Derivative(r(x, y), x)*Subs(Derivative(f(_xi_1, phi(x, y)), _xi_1), _xi_1, r(x, y))
My question is: how can I replace Subs(Derivative(f(_xi_1, phi(x, y)), _xi_1) by df_dr?
i wrote a pow function in ocaml and by mistake a wrote this
let rec pow x y acc = if y = 1 then acc else pow x (y-1) x*x;;
this function can be called with any value of acc and output the correct answer, but this must output x^2 .
this is the correct functon :
let rec pow x y acc = if y = 0 then acc else pow x (y-1) x*acc;;
and call this function with the value of acc of 1.
my question is why first function give the correct output ?
The key is that function application has higher precedence than binary operators. In the case at hand, the else term is equivalent to (pow x (y-1) x) * x, not pow x (y-1) (x*x).
I have a problem doing one of the questions from my programming lab.
The question was like "Given the variables x, y, and z, each associated with an int, write a fragment of code that assigns the smallest of these to min."
And my work area looks like
if x < y and x < z:
x = min
if y < x and y < z:
y = min
if z < x and z < y:
z = min
When I turned in, the feedback said:
Remarks:
⇒ Unexpected identifiers: and
More Hints:
⇒ Solutions with your approach don't usually use: <
although I tried may ways to figure it out but none of them worked.
Plz help.
Thx.
For the first reply, the system said:
Remarks:
⇒ Unexpected identifiers: and
More Hints:
⇒ Solutions with your approach don't usually use: <
Problems Detected:
⇒ Exception occurred(, TypeError('unorderable types: int() < builtin_function_or_method()',), )
⇒ Exception occurred(, TypeError('unorderable types: int() < builtin_function_or_method()',), )
⇒ Exception occurred(, TypeError('unorderable types: int() < builtin_function_or_method()',), )
⇒ Exception occurred(, TypeError('unorderable types: int() < builtin_function_or_method()',), )
⇒ min does not contain the correct value
⇒ y was modified
⇒ z was modified
For the second reply, the system said:
Remarks:
⇒ Unexpected identifiers: and, def, minist
⇒ You have to use the min variable .
⇒ You should use an assignment operator (=) in this exercise.
More Hints:
⇒ You almost certainly should be using: =
⇒ You almost certainly should be using: min
⇒ I haven't yet seen a correct solution that uses: , (comma)
I see three issues with the code as you've shown it in the question.
The first is that your indentation is a bit messed up. You probably want all your if statements to be at the same level, with the corresponding assignment statements indented under each one:
if something:
foo = bar
if something_else:
foo = baz
# etc
You could also use elif statements instead of the second and third if, since you never expect to have more than one of the conditions true at the same time.
The second issue is that you're doing your assignment statements backwards. If you want to assign the value in a variable x to a new variable named min, you should put min on the left side and x on the right:
min = x
This is part of the reason you're getting lots of confusing errors. Before your code runs, min is the name of a builtin function (which I suspect you'll learn about later in your class). When you did x = min you were replacing the old x value with a reference to the function.
The last thing is a logic issue. Your comparisons are all using the < operator to test if one value is smaller than the others. The issue is what happens if two of the values are equal. If x and y have the same value, both x < y and y < x will be False. That's not very good for your code, and so you probably want to use the <= operator instead. It tests if the left side is less than or equal to the right side. With this version, if you're using elifs, you can actually do away with the last condition and just use else, since if neither x or y is less than or equal to the other values, z must be the smallest value by process of elimination.
Anyway, here's the code with all three issues fixed:
if x <= y and x <= z:
min = x
elif y <= x and y <= z:
min = y
else: # no "z <= x and z <= y" check needed here, will always be true if reached
min = z
Maybe the tab problem.
You can try this:
if x < y and x < z:
x = min
if y < x and y < z:
y = min
if z < x and z < y:
z = min
I make a sample:
#-*- coding:utf-8 -*-
def minist(x,y,z):
if x < y and x < z:
return x
if y < x and y < z:
return y
if z < x and z < y:
return z
x = 1
y = 2
z = 3
test = -1
test = minist(x,y,z)
print(test)
This sample will print 1.
I want to make a recursive function that sums the integers between two values. I'm doing:
let rec sum_between x y =
if x>y then sum_between y x else
if x=y then x else x + sum_between x+1 y ;;
But I get the error: This expression has type int -> int
but an expression was expected of type int
What am I doing wrong?
Function application has high precedence in OCaml. You need to parenthesize an expression when it's an argument to a function.
Your code
sum_between x+1 y
is parsed like this:
(sum_between x) + (1 y)
You need parentheses:
sum_between (x + 1) y
(Same answer as Edgar Aroutiounian but more helpful detail I hope.)
Assuming pos_of_xy (x, y) n is already defined to return an int, this code segment exits once one of the if statements returns false as if they were nested. I need them all to run regardless of the previous if statements. I'm not sure what I am forgetting.
let final = ref [] in begin
if x < (size-1) then let pos = pos_of_xy (x+1, y) size in final := pos::!final;
if y < (size-1) then let pos = pos_of_xy (x, y+1) size in final := pos::!final;
if y > 0 then let pos = pos_of_xy (x, y-1) size in final := pos::!final;
if x > 0 then let pos = pos_of_xy (x-1, y) size in final := pos::!final;
end;
One way of describing the problem is that let is stronger than if. A let takes a sequence of statements after in, and your subsequent ifs are treated as part of this sequence. Things should work if you parenthesize each let:
if x < size - 1 then
(let pos = pos_of_xy (x + 1, y) size in final := pos :: !final);
Or you could do without the let:
if x < size -1 then final := pos_of_xy (x + 1, y) size :: !final;
As a side comment, the code might look even nicer to an FP progammer if you wrote in a more functional style (without the mutable value).
Update
Here's a quick sketch of a more functional way to calculate your list:
let good (x, y) = x >= 0 && x < size && y >= 0 && y < size in
let topos (x, y) = pos_of_xy (x, y) size in
let goodxy =
List.filter good [(x + 1, y); (x, y + 1); (x - 1, y); (x, y - 1)] in
List.map topos goodxy
As Jeffrey Scofield said, let has lower precedence than if. So it's as if you wrote:
let final = ref [] in begin
if x < (size-1) then (let pos = pos_of_xy (x+1, y) size in (final := pos::!final;
(if y < (size-1) then (let pos = pos_of_xy (x, y+1) size in (final := pos::!final;
(if y > 0 then (let pos = pos_of_xy (x, y-1) size in (final := pos::!final;
(if x > 0 then (let pos = pos_of_xy (x-1, y) size in (final := pos::!final;)))))))))))
end;
You can look at the table of precedences here (scroll up a little). As you can see, if has higher precedence than ;, which has higher precedence than let.