Haskell 98报告
顶部|后面|下一个|目录|功能索引

14  数字


数字模块(来自Rat,
showSigned、showIntAtBase、,
showInt、showOct、showHex、,
readSigned、readInt、,
readDec、readOct、readHex、
浮点到数字,
showEFloat,showFFloat,showGFloat,显示浮动
readFloat,lexDigits),其中

fromRat::(RealFloat a)=>有理->a

showSigned::(Real a)=>(a->ShowS)->Int->a->ShowsS
showIntAtBase::积分a=>a->(Int->Char)->a->ShowS
showInt::积分a=>a->ShowS
showOct::积分a=>a->ShowS
showHex::积分a=>a->ShowS

readSigned::(Real a)=>ReadS a->ReadS a读取签名::(实a)=>ReadS a
readInt::(积分a)=>
a->(Char->Bool)->(Char->Int)->读取S
readDec::(积分a)=>ReadS a
readOct::(积分a)=>ReadS a
readHex::(积分a)=>ReadS a

showEFloat::(RealFloat a)=>可能是Int->a->ShowS
showFFloat::(RealFloat a)=>可能是Int->a->ShowS
showGFloat::(RealFloat a)=>可能是Int->a->ShowS
showFloat::(RealFloat a)=>a->ShowS

floatToDigits::(RealFloat a)=>整数->a->([Int],Int)

readFloat::(RealFrac a)=>读取S
lexDigits::读取S字符串
此库包含各种数字函数,其中许多是在标准前奏曲中使用。

在下面的内容中,从前奏曲:
 
类型ShowS=字符串->字符串
type ReadS=字符串->[(a,字符串)]

14.1  显示功能

14.2  正在读取函数

(注:读取Int是的“双重”显示IntAtBase、和读取十二月是的“双重”显示Int.命名不一致是历史上的意外。)

14.3  其他

14.4  图书馆数字


数字模块(来自Rat,
showSigned、showIntAtBase、,
showInt、showOct、showHex、,
readSigned、readInt、,
readDec、readOct、readHex、
浮点到数字,
showEFloat,showFFloat,showGFloat,显示浮动
readFloat,lexDigits),其中

导入字符(isDigit、isOctDigit和isHexDigit
,数字到整数,整数到数字)
导入比率(%),分子,分母)
导入数组((!),数组,数组)

--这将有理数转换为浮动。这应该用于
--Float和Double的分数实例。

fromRat::(RealFloat a)=>理性->a
from大鼠x=
如果x==0,则encodeFloat 0 0--处理异常情况
否则,如果x<0,那么-fromRat'(-x)--首先。
其他来自Rat'x

--转换过程:
--按RealFloat基数缩放有理数,直到
--它位于尾数的范围内(decodeFloat/encodeFloat使用的尾数)。
--然后将有理数舍入为整数,并用指数对其进行编码
--我们从缩放中得到的。
--为了加快缩放过程,我们计算要得到的数字的log2
--指数的第一个猜测。
fromRat'::(RealFloat a)=>有理->a
fromRat'x=r
其中b=float基数r
p=浮点数字r
(最小Exp0,_)=浮动范围r
minExp=minExp0-p——实际最小指数
xMin=到有理数(expt b(p-1))
xMax=合理值(expt b p)
p0=(整数LogBase b(分子x)-
integerLogBase b(分母x)-p)`max`minExp
f=如果p0<0,则1%导出b(-p0),否则导出b p0%1
(x',p')=比例Rat(到有理b)最小膨胀x最小x最大p0(x/f)
r=编码浮点(圆形x')p'

--缩放x直到xMin<=x<xMax,或p(指数)<=minExp。
scaleRat::Rational->Int->Rational->Rational
Int->有理->(有理,Int)
scaleRat b最小膨胀x最小x最大p x=
如果p<=minExp,则
(x,p)
否则,如果x>=xMax,则
scaleRat b最小膨胀x最小x最大(p+1)(x/b)
否则,如果x<xMin,则
比例尺大鼠b最小Exp x最小x最大(p-1)(x*b)
其他
(x,p)

--使用缓存对最常见的数字进行指数运算。
minExpt=0::内部
最大出口=1100::内部
expt::Integer->Int->Integer
expt基数n=
如果基数==2&&n>=minExpt&&n<=maxExpt,则
出口!n个
其他
基数^n

expts::数组整数
expts=数组(minExpt,maxExpt)[(n,2^n)|n<-[minExpt..maxExpt]]

--计算以b为底的i的对数(底面)。
--最简单的方法是将i除以b,直到它小于b,
--但那会很慢!我们只是稍微聪明一点。
integerLogBase::Integer->Integer->Int
integerLogBase b i=
如果i<b,则
0个
其他
--试着先把底座展平,以减少除法数。
设l=2*integerLogBase(b*b)i
doDiv::整数->整数->整数
doDiv i l=如果i<b,则l为doDiv(i`div`b)(l+1)
在doDiv(i`div`(b^l))l中


--显示整数和浮点的其他实用程序

showSigned::真实a=>(a->ShowS)->Int->a->ShowsS
show签名showPos p x
|x<0=showParen(p>6)(showChar“-”.showPos(-x))
|否则=showPos x

--showInt、showOct、showHex仅用于正数
showInt,showOct,showHex::积分a=>a->ShowS
showOct=showIntAtBase 8整数到数字
showInt=showIntAtBase 10整数到数字
showHex=showIntAtBase 16整数到数字

showIntAtBase::积分a
=>a--基数
->(Int->Char)--数字到字符
->a--要显示的数字
->显示S
showIntAtBase基数intToDig n rest
|n<0=error“Numeric.showIntAtBase:无法显示负数”
|n'==0=休息'
|否则=showIntAtBase base intToDig n“rest”
其中
(n’,d)=引用n基数
rest’=intToDig(from Integral d):rest


readSigned::(Real a)=>ReadS a->ReadS a读取签名::(实a)=>ReadS a
readSigned readPos=readParen False读取'
其中read‘r=read’r++
[(-x,t)|(“-”,s)<-法r,
(x,t)<-读取's]
读取“”r=[(n,s)|(str,s)<-lex r,
(n,“”)<-readPos字符串]


--readInt使用任意基数读取数字串。  
--前面的减号必须在别处处理。

readInt::(积分a)=>a->(Char->Bool)->(Char->Int)->ReadS a
readInt基数是Dig digToInt=
[(foldl1(\n d->n*基数+d)(map(from Integral.digToInt)ds),r)
|(ds,r)<-nonnull isDig s]

--各种基础的未签名读者
readDec,readOct,readHex::(积分a)=>ReadS a
readDec=readInt 10是数字到Int
readOct=readInt 8是OctDigit数字ToInt
readHex=readInt 16是HexDigit数字ToInt


showEFloat::(RealFloat a)=>可能是Int->a->ShowS
showFFloat::(RealFloat a)=>可能是Int->a->ShowS
showGFloat::(RealFloat a)=>可能是Int->a->ShowS
showFloat::(RealFloat a)=>a->ShowS

showEFloat d x=showString(formatRealFloat FFExponent d x)
showFFloat d x=showString(formatRealFloat FFFixed d x)
showGFloat d x=showString(formatRealFloat FFGeneric d x)
showFloat=showGFloat无

--这些是格式类型。不导出此类型。

data FFFormat=FFExponent | FFFixed | FFGeneric

formatRealFloat::(RealFloat a)=>FFFormat->Maybe Int->a->String
格式RealFloat fmt decs x
=秒
其中
基数=10
s=如果isNaN x,则
“不适用”
否则如果是无限x那么
如果x<0,则为“-无限”,否则为“无限”
否则,如果x<0||为负零x,则
“-”:doFmt fmt(floatToDigits(toInteger基数)(-x))
其他
doFmt fmt(浮点到数字(以整数为基数)x)
    
doFmt fmt(是,e)
=出租
ds=映射intToDigit为
英寸
案例fmt
FF通用->
doFmt(如果e<0||e>7,则为FFExponent else FFFixed)
(是,e)
FF指数->
病例数减少
什么都没有->
案例ds
[]->“0.0e0”
[d]->d:“.0e”++节目(e-1)
d:ds->d:':ds++“e”:显示(e-1)
          
刚刚12月->
让dec'=最大dec 1英寸
案例属于
                  [] -> '0':'.':take dec'(重复'0')++“e0”
_->
let(ei,is’)=roundTo base(dec'+1)为
d:ds=映射intToDigit
(如果ei>0,则init为“else is”)
在d:“.”中:ds++“e”++显示(e-1+ei)
          
FF固定->
病例数减少
无--始终打印小数点
|e>0->take e(ds++重复“0”)
                                ++ '.':mk0(删除)
|否则->“0.”++mk0(复制(-e)'0'++ds)
              
仅dec->—当dec>0时打印小数点
让dec'=最大dec 0 in
如果e>=0,则
let(ei,is’)=圆到底(dec’+e)为
(ls,rs)=splitAt(e+ei)
(intToDigit映射为')
在mk0 ls++mkdot0 rs中
其他
let(ei,is’)=roundTo base dec'
(复制(-e)0++是)
d:ds=映射intToDigit
(如果ei>0,则为“else 0:is”)
在d:mkdot0 ds中
其中
mk0“”=“0”--打印0.34,而不是.34
mk0秒=秒
    
mkdot0“”=“”--打印34,而不是34。
mkdot0 s=“.”:s--当格式指定否时
--小数点后的数字
    

roundTo::Int->Int->[Int]->(Int,[Int])
roundTo base d is=f d为的情况
(0,is)->(0,s)
(1,is)->(1,1:is)
其中b2=基数`div`2
f n[]=(0,复制n 0)
f 0(i:_)=(如果i>=b2,则1为0,[])
f d(i:is)=
设(c,ds)=f(d-1)为
i’=c+i
如果i'==基,则(1,0:ds)else(0,i':ds)

--
--基于“快速准确打印浮点数”
--由R。G.汉堡和R。英国。Dybvig,采用PLDI 96。
--这里的版本使用了一个慢得多的对数估计量。  
--它应该改进。

--此函数返回一个非空的数字列表([0..base-1]中的整数)
--和指数。一般来说,如果
--浮点到数字r=([a,b,…z],e)
--然后
--r=0.ab..z*基数^e
-- 

floatToDigits::(RealFloat a)=>整数->a->([Int],Int)

floatToDigits _ 0=([],0)
floatToDigits基数x=
let(f0,e0)=解码浮点x
(最小Exp0,_)=浮动范围x
p=浮点数字x
b=浮基数x
minExp=minExp0-p——实际最小指数

--Haskell要求将f调整为非规范化数字
--将有一个不可能的低指数。对此进行调整。
f::整数
e::国际
(f,e)=设n=最小Exp-e0
如果n>0,则(f0`div`(b^n),e0+n)else(f0,e0)

(r、s、mUp、mDn)=
如果e>=0,则
设为b^e
如果f==b^(p-1),则
(f*be*b*2,2*b,be*b,b)
其他
(f*be*2,2,be,be)
其他
如果e>minExp&&f==b^(p-1),则
(f*b*2,b^(-e+1)*2,b,1)
其他
(f*2,b^(-e)*2,1,1)
k=
设k0=
如果b==2&&base==10,则
--logBase 10 2略大于3/10,因此
--以下将出现低端错误。忽略
--分数会使其误差更大。
——Haskell承诺p-1<=logBase b f<p。
(p-1+e0)*3`div`10
其他
上限((log(fromInteger(f+1))+
fromIntegral e*log(fromInteger b))/
log(从整数基数)
固定装置n=
如果n>=0,则
如果r+mUp<=导出基数n*s,则n其他修正(n+1)
其他
如果expt基数(-n)*(r+mUp)<=s,则n
else修正(n+1)
在链接地址k0中

发电机ds rn sN mUpN mDnN=
let(dn,rn')=(rn*base)`divMod`sN
mUpN'=mUpN*基数
mDnN'=mDnN*基数
如果(rn’<mDnN’,rn’+mUpN’>sN)
(正确,错误)->dn:ds
(假,真)->dn+1:ds
(真,真)->如果rn'*2<sN,则dn:ds其他dn+1:ds
(假,假)->gen(dn:ds)rn'sN mUpN'mDnN'
无线电数据系统=
如果k>=0,则
gen[]r(s*expt base k)mUp mDn
其他
设bk=导出基数(-k)
在gen[](r*bk)s(mUp*bk
in(积分映射(反向rds),k)



--此浮点读取器对浮点使用限制较少的语法
--比Haskell lexer点。“.”是可选的。

readFloat::(RealFrac a)=>读取S
readFloat r=[(从有理数((n%1)*10^^(k-d)),t)|(n,d,s)<-readFix r,
(k,t)<-读取Exp s]++
[(0/0,t)|(“NaN”,t)<-lex r]++
[(1/0,t)|(“无限”,t)<-lex r]
其中
readFix r=[(读取(ds++ds'),长度ds',t)
|(ds,d)<-lex数字r,
(ds’,t)<-lexFrac d]
               
lexFrac('.':ds)=lexDigits ds
lexFrac s=[(“”,s)]
                 
readExp(e:s)|e`elem`“eE”=readExp的
读Exp s=[(0,s)]
                 
readExp'('-':s)=[(-k,t)|(k,t
readExp'('+':s)=读取Dec s
readExp’s=readDec s

lexDigits::读取S字符串
lexDigits=非空isDigit

非空::(Char->Bool)->读取S字符串
非空p s=[(cs,t)|(cs@(_:_),t)<-[span p s]]


Haskell 98报告
顶部|后面|下一个|目录|功能索引
2002年12月