要在OCaml中浮动的字符串:上下近似

时间:2016-10-24 13:34:44

标签: ocaml rounding-error

给定一个(可能是大的)整数的字符串,我需要在OCaml中将其转换为浮点数。问题是由于舍入错误,转换并不总是准确的。例如,float_of_string "61035156250000000000"将返回61035156249999998976。如何对数字进行粗略近似和过高近似以获得间隔[a, b]

  1. a是最大的可表示浮点数,例如a <= 61035156250000000000
  2. b是最小的可表示浮点数,例如b >= 61035156250000000000

2 个答案:

答案 0 :(得分:1)

您必须获得一个近似值,包括准确值(可能无法表示为float)和二分搜索。这是我写的一个简短的程序:

from bs4 import BeautifulSoup
import urllib
import urllib2
import requests

#driver = webdriver.Firefox()
url = "http://www.forever21.com/Product/Category.aspx?br=f21&category=dress&pagesize=100&page=1"
#r = driver.get(url)
#html = r.read()
#headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36'}
#html = requests.get(url, headers=headers)
#response = opener.open(url)
#html = response.read()
html = urllib.urlopen(url).read()
soup = BeautifulSoup(html, "html.parser")
print soup

使用Num模块编译以获得此输出:

let num_of_float x =
   let two = Num.num_of_int 2 in
   let rec expand x =
      let fr, wh = modf x in
      Num.add_num (Num.num_of_int (int_of_float wh))
      (if fr = 0.0 then Num.num_of_int 0 else
      Num.div_num (expand (2.0*.fr)) two) in
   let fl, ex = frexp x in
   if ex <> 0 then Num.mult_num (expand fl) (Num.power_num two (Num.num_of_int ex))
   else
      expand x

let bracket str =
   let x = Num.num_of_string str in
   let rec binsearch a b =
      let t = (b-.a)*.0.5 +. a in
      if (t = a) || (t = b) then (a,b) else
      match Num.compare_num x (num_of_float t) with
        | -1 -> binsearch a t
        | 0 -> (t,t)
        | 1 -> binsearch t b
        | _ -> failwith "compare_num" in
   let near = Num.float_of_num x in
   let delta = 1.0 +. (4.0*.epsilon_float) in
      binsearch (near/.delta) (near*.delta)

let () =
   let l,r = bracket "61035156250000000000" in
   Printf.printf "[%.16g = %s, %.16g = %s]\n"
    l (Num.string_of_num (num_of_float l)) r (Num.string_of_num (num_of_float r))

您需要调整增量值并检查NaN,无穷大和转换错误,以获得稳健的方法。

答案 1 :(得分:0)

这是因为浮点数存储为A_ * pow(2,B _)。

你需要的是一个BigInt http://caml.inria.fr/pub/docs/manual-ocaml/libref/Big_int.html