Error handling 当使用int\u of_float从float转换时,如何处理OCaml中的整数溢出?

Error handling 当使用int\u of_float从float转换时,如何处理OCaml中的整数溢出?,error-handling,ocaml,Error Handling,Ocaml,这里是OCaml新手 我试图弄清楚如何在从float转换为int时处理OCaml中的整数溢出 我想用试试。。。使用…或将其与nan(实际上是从?)进行比较,但看起来它不会抛出任何错误。 更令人惊讶的是,对于非常大的浮点,int\u of\u float只返回0 utop # 0 = int_of_float 9999999999999999999.0;; - : bool = true utop # int_of_float 9999999999999999999.0;; - : int = 0

这里是OCaml新手

我试图弄清楚如何在从float转换为int时处理OCaml中的整数溢出

我想用
试试。。。使用…
或将其与
nan
(实际上是从?)进行比较,但看起来它不会抛出任何错误。 更令人惊讶的是,对于非常大的浮点,int\u of\u float只返回
0

utop # 0 = int_of_float 9999999999999999999.0;;
- : bool = true
utop # int_of_float 9999999999999999999.0;;
- : int = 0
如何正确处理浮点到整数的转换?(更普遍的是int溢出?

事实上,如果参数为nan或不在可表示整数的范围内,则表明int的
float\u“结果未指定。”

一种可能性是事先检查您的浮动是否合适,并返回一个选项或引发一个异常,例如

let safe_int_of_float f =
  if classify_float f = FP_nan then None
  else if f >= float_of_int max_int then None
  else if f <= float_of_int min_int then None
  else Some (int_of_float f)
让safe\u int\u浮起f=
如果分类浮点数f=FP\u nan,则无
否则,如果f>=浮点值,则为无

否则,如果f以下模块将执行此操作

(*
   This module defines the range of integers that can be represented
   interchangeably with the float or with int type.

   Note that this range depends on size of the int type, which depends
   on the compilation target.
*)

(*
   OCaml ints have 31 bits or 63 bits.
   OCaml floats are double-precision floats (IEEE-754 binary64).
*)
let int_range_min_float = max (-.2.**53.) (float min_int)
let int_range_max_float = min (2.**53.) (float max_int)

let exact_int_of_float x =
  if x >= int_range_min_float && x <= int_range_max_float then
    truncate x
  else
    invalid_arg "exact_int_of_float: out of range"

let int_range_min_int = exact_int_of_float int_range_min_float
let int_range_max_int = exact_int_of_float int_range_max_float

let exact_float_of_int x =
  if x >= int_range_min_int && x <= int_range_max_int then
    float x
  else
    invalid_arg "exact_float_of_int: out of range"

let test () =
  let imin, imax = int_range_min_int, int_range_max_int in
  let fmin, fmax = int_range_min_float, int_range_max_float in
  assert (exact_int_of_float 1. = 1);
  assert (exact_int_of_float (-1.) = -1);
  assert (fmin < 0.);
  assert (fmax > 0.);
  assert (imin < 0);
  assert (imax > 0);
  assert (float (truncate fmin) = fmin);
  assert (float (truncate fmax) = fmax);
  assert (truncate (float imin) = imin);
  assert (truncate (float imax) = imax);
  assert (float (imin + 1) = float imin +. 1.);
  assert (float (imin + 2) = float imin +. 2.);
  assert (float (imax - 1) = float imax -. 1.);
  assert (float (imax - 2) = float imax -. 2.)
(*
此模块定义可表示的整数范围
可与float或int类型互换。
请注意,此范围取决于int类型的大小,而int类型的大小取决于
关于编译目标。
*)
(*
OCaml int有31位或63位。
OCaml浮点是双精度浮点(IEEE-754二进制64)。
*)
设int_range_min_float=max(-.2.*53.)(float min_int)
设int_range_max_float=min(2.**53.)(float max_int)
让精确的浮点数为x=
如果x>=int_range_min_float&&x=int_range_min_int&&x 0.);
断言(imin<0);
断言(imax>0);
断言(浮点(截断fmin)=fmin);
断言(浮点(截断fmax)=fmax);
断言(truncate(float imin)=imin);
断言(截断(浮点imax)=imax);
断言(float(imin+1)=float imin+1);
断言(float(imin+2)=float imin+2);
断言(float(imax-1)=float imax-.1.);
断言(float(imax-2)=float imax-.2.)

只是对您的第一个问号的澄清:当手册上说如果参数为nan或超出可表示整数的范围,则结果未指定时,实际上意味着任何事情都可能发生,因此没有什么令人惊讶的。确切地说,这是未指定的,因为他们不想承诺任何特定的行为(这可能会阻止未来版本中的优化和更改)。或者引发您选择的异常不幸的是,这需要更多的工作。例如,
int\u of_float(float\u of_int max\u int)
的计算结果为负int(至少在64位平台上,int可以比float更精确地表示,从而导致舍入问题)。@MartinJambon你当然是对的。我对代码进行了编辑,使用了非严格不等式,应该可以做到这一点。至少对
(float\u of\u int max\u int)*是这样的。(1.-epsilon\u float)
及其
min\u int
对应项。当然,从Coq证明中提取的代码将受到欢迎。谢谢。这很方便,因为我刚刚意识到OCaml无法处理,例如,下面的表达式
Int\u of_float(float\u of_Int(max_Int))#和%$疯狂。