It contains the modf function, which is a Swiss knife function with which you can define the truncatef and roundf :
# let truncatef x = snd (modf x);; val truncatef : float -> float = <fun>
The round function can also be expressed using modf
# let roundf x = snd (modf (x +. copysign 0.5 x));; val roundf : float -> float = <fun>
However, it can be expressed more concisely (and effectively) using floor
# let roundf x = floor (x +. 0.5)
But both rounding functions are a bit erroneous as the comment in the core implementation:
(* Outside of the range [round_nearest_lb..round_nearest_ub], all representable doubles are integers in the mathematical sense, and [round_nearest] should be identity. However, for odd numbers with the absolute value between 2**52 and 2**53, the formula [round_nearest x = floor (x + 0.5)] does not hold: # let naive_round_nearest x = floor (x +. 0.5);; # let x = 2. ** 52. +. 1.;; val x : float = 4503599627370497. # naive_round_nearest x;; - : float = 4503599627370498. *) let round_nearest_lb = -.(2. ** 52.) let round_nearest_ub = 2. ** 52.
So, a more correct way to implement rounding would be (from the Core library):
let round_nearest t = if t >= round_nearest_lb && t <= round_nearest_ub then floor (t +. 0.5) else t
But even this round_nearest not perfect, for example:
# round_nearest 0.49999999999999994;; - : float = 1.
This 0.49999999999999994 is the immediate predecessor of 0.5 . The Pascal blog contains suggestions for solving this problem. The following should work in OCaml:
let round_nearest t = if t >= round_nearest_lb && t <= round_nearest_ub then floor (t +. 0.49999999999999994) else t # round_nearest 0.49999999999999994;; - : float = 0. # round_nearest (~-.0.49999999999999994);; - : float = 0. # round_nearest (~-.1.49999999999999994);; - : float = -1. # round_nearest 0.5;; - : float = 1. # round_nearest ~-.0.5;; - : float = -1. #
And this is only one rounding policy, rounded to the nearest (intuitive). There are other policies that have their own reservations.