获取OCaml中浮动的精度

时间:2016-12-13 10:38:58

标签: ocaml

我想获得我的应用程序的十进制数的精度, 我尝试了几种方法,但我无法得到我想要的东西。

在启动时,我试图将浮点数转换为字符串,并对其进行简单拆分并将其存储在整数列表中,然后获取列表的长度

let a = 12.12345678910111213141516;;
let stringA = string_of_float a;;

let list_of_ints stringA = List.map int_of_string (Str.split (Str.regexp "\.") stringA);;
let stringList = list_of_ints stringA;;
let thedecimal = string_of_int (List.nth stringList 1);;

S.length thedecimal;;

问题是每当我在浮动的特征方面有超过10个数字它不起作用时,它总是返回10

val a : float = 12.1234567891011125
val stringA : string = "12.1234567891"
val list_of_ints : string -> int list = <fun>
val stringList : int list = [12; 1234567891]
val thedecimal : string = "1234567891"
- : int = 10

我的第二种方法是尝试在浮点数和。之间进行减法 它的特点是,我得到了尾数,然后把它存放在一个清单上 得到它的长度减2(0和。)

let b = int_of_float a;;
let c = a -. (float_of_int b);;
S.length (string_of_float c)-2;; 

它返回12,这很奇怪,因为我期待23,

val b : int = 12
val c : float = 0.123456789101112463
- : int = 12

我是Ocaml的新手。如果有人对如何获得精确度有任何解决方案,我需要你的帮助,谢谢你。

2 个答案:

答案 0 :(得分:1)

显然,string_of_float决定将显示的有效数字的数量限制为十二(我必须仔细研究它)。

这实际上是一件好事,因为双倍可以表示为一个非常大的数字。

# let f = 0.123456789012345678901234567890;;   
val f : float = 0.123456789012345677
# let s = string_of_float f;;
val s : string = "0.123456789012"
# let s' = Printf.sprintf "%.10f" f;;
val s' : string = "0.1234567890"
# let s'' = Printf.sprintf "%.30f" f;;
val s'' : string = "0.123456789012345677369886232100"
# let s''' = Printf.sprintf "%.60f" f;;
val s''' : string =
  "0.123456789012345677369886232099815970286726951599121093750000"
(* longer than this one just add zeroes *)

现在,您要求的数字实际精确度。根据{{​​3}}:

  
      
  • 符号位:1位
  •   
  • 指数:11位
  •   
  • 显着精度:53位(显式存储52位)
  •   

而且......

  

使用带有隐式整数的有效数字编写格式   值为1的位(特殊数据除外,请参见指数编码   下面)。随着分数有效数的52位出现在   因此,存储器格式的总精度为53位(约为   16位十进制数,53 log10(2)≈15.955)。

     

在252 = 4,503,599,627,370,496和253 = 9,007,199,254,740,992之间   可表示的数字正是整数。对于下一个范围,   从253到254,一切都乘以2,所以可以表示   数字是偶数,等等。相反,对于前一个范围   从251到252,间距为0.5等。

     

间距为数字的一部分,范围为2n至2n + 1   是2n-52。舍入数字时的最大相对舍入误差   因此,到最近的可表示的(机器epsilon)   2-53。

所以你拥有它,你的浮动值的精确度大约为2^-53。对于任何浮点数,这为您提供 15或16位精度的十进制数字

作为旁注,如果你在浮标上使用正则表达式,你需要冷静下来并考虑一下小猫。

答案 1 :(得分:1)

由于双精度表示中的位数有限,最大精度为324.请参阅Wikipedia

  

通过降低精度,次正规表示允许更小的值达到约5×10-324。

以下功能就是您想要的。

let precision_of_float f = 
  let (fractional, _) = modf f in
  let fractional_string = (Printf.sprintf "%.324f" fractional) in 

  (* remove ending zeros *)
  let fractional_string = Str.replace_first (Str.regexp "0+$") "" fractional_string in

  (* fractional_string is of the form 0.[0-9]* *)
  String.length fractional_string - 2