Ocaml vs Python - Function return value

Asked

Viewed 81 times

1

I have the following function written in ocaml

let rec pow((x:int), (y:int)) : int =
  if y=0 then
    1
  else
    x * pow(x,y-1)
;;
let pr = 13;;
let bs = 31;;
let getvalor num ch1 ch2 tam =
  (num * bs + int_of_char(ch1) - int_of_char(ch2) * (pow(bs, tam) mod pr)) mod pr
;;
print_int (getvalor 1 'A' 'A' 2);;

In print returns -8 and implemented a similar python function and returned this value 5 but I’m not sure why the values are different in both outputs.

Python version:

def int_of_char(char):
  return ord(char)
def getvalor(num, ch1, ch2, bs, length, nmb2):
  return (num * bs + int_of_char(ch1) - int_of_char(ch2) * pow(bs, length, nmb2)) % nmb2

print (getvalor (1,'A','A',31,2,13)) 
  • How you implemented this potentiation between integers in Ocaml?

  • forgot to put. I already did update

  • Obs for those who do not know the Ocaml language, try to do 2 ** 3 or else, if my memory doesn’t fail me, something like this float_of_int 2 ** float_of_int 3|> int_of_float

1 answer

1


Answering your question "because the values are different in the two outputs?".

That function pow() that defined in Ocaml works well with small numbers:

# pow(2,5) ;;
- : int = 32

However in the required magnitude in its calculation bs=31 and tam=412 the result sometimes exceeds the value of max_int:

# max_int;;
- : int = 4611686018427387903

Breaking the numerical limit and returning a negative value, remembering positive power of positive integers the result is always positive.

# pow(31,412) ;;
- : int = -1355500415

Already in python the builtin pow() will return the correct value because in python there is virtually no limit to integers:

>>> print(pow(31,412))
276069138324941945105491334106743548343721891253395677647688980210268338479815494895702857569705905259215554766122880414081265412222862455070422343941123563226292693898588710424868593004715576400093926321790564436401576623753610968630429707481035503096221766405055115180414065291029160680597540318300168902837206474368389783537831824941035360031248630200395997664286279876185196611747109383548663603552453004476274809140462798037718731829815781875721556412228287401860555521034466663555186417962593312862133585901989904028712225121222048901049818453241421257430604049981206904806269761521337270272284591644143301761

In Ocaml instead of performing these calculations with the type int use some numerical type of arbitrary precision.

Editing:

As AP restricted the function domain, another problem appeared. There is a difference in the way that Ocaml treats the operator mod and the way Python treats the operator %.

To definition of module says that given two positive numbers, a and b , a module b (abbreviated as mod b ) is the remainder of euclidean division of a for b:

a = bq + r

Where:

  • a is the dividend.
  • b is the divider.
  • q is the quotient.
  • r is the rest.

When dividend and divisor are positive all right, the problem is when one of the operators is negative and two results are mathematically possible.

Another factor that influences the result is the way languages treat the entire division:

  • In Ocaml the entire division is rounded to 0, which makes the module result always have the same signal as the dividend.
  • In Python the entire division always rounds down (towards negative infinity), which makes the module result always have the same signal as the divisor.

An example of divergence would be module of the division of -684 for 13:

In Ocaml:

# -684 mod 13 ;;
- : int = -8

Python:

>>> -684 % 13
5

So it’s two solutions. One solution would be to make the code Ocaml behave like the code Python, the other solution would be to make the code Python behave like the code Ocaml.

First Alternative: Making Code Ocaml behave like Python:

To make the operator Ocaml mod present the same result as in Python the operator must be reimplemented:

# let (mod) x y = let res = x mod y in if res < 0 then res + y else res;;

Or in your code:

let rec pow((x:int), (y:int)) : int =
  if y=0 then
    1
  else
    x * pow(x,y-1)
;;

let (mod) x y = let res = x mod y in if res < 0 then res + y else res;;

let pr = 13;;
let bs = 31;;
let getvalor num ch1 ch2 tam =
  (num * bs + int_of_char(ch1) - int_of_char(ch2) * (pow(bs, tam) mod pr)) mod pr
;;

Resulting:

# print_int (getvalor 1 'A' 'A' 2);;
5

Second Alternative: Making Code Python behave like Ocaml:

In that case it is sufficient to replace the operator Ocaml mod for its equivalent Python math.fmod()

from math import fmod

def int_of_char(char):
  return ord(char)
def getvalor(num, ch1, ch2, bs, length, nmb2):
  return int(fmod(num * bs + int_of_char(ch1) - int_of_char(ch2) * fmod(pow(bs, length), nmb2), nmb2))

Resulting:

>>>print (getvalor (1,'A','A',31,2,13)) 
-8

Using one or another solution depends on your intention.

  • I changed the values of the variables to be possible to represent in both programs but returns different results

  • Still having the same problem pow(31,13) ;;&#xA;- : int = -505558625 see: https://imgur.com/a/Bu3PhpP

  • 1

    Pow (31,2) I think it’s like this

  • I decompose the operation in python https://repl.it/repls/DotingDapperEmulation I will do the same in Ocalm...

  • In Ocalm gave a=96 b=-780 c=-684 d=-8. When you do it in python (...) % nmb2 he returns 5 and in Ocalm (...) mod nmb2 is returning -8

  • If you do the same account on google calculator the result will be 5 the same result as in python

  • But if you do 684 % 13(Positive value) the result is 8

  • That means in Ocaml when it does mod of a negative the interpreter converts the negative to positive and then calculates the remainder and then adds the signal.

  • To return the value 5 in ocaml I must do what?

  • @user185544 I made an edition in the reply I hope it satisfies you.

  • Regarding the arbitrary precision numbers I am unable to load the library to the program #load "nums.cma";; returns syntax error when trying to compile

  • Then I can’t help because it runs away from my area, it’s already infrastructure case. It’s a matter of putting the libs in the right directory and making OS notes.

Show 7 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.