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