Haskell 如何将有理数转换为;“漂亮”;一串
我想在十进制扩展中显示一些Haskell 如何将有理数转换为;“漂亮”;一串,haskell,formatting,rational-number,Haskell,Formatting,Rational Number,我想在十进制扩展中显示一些Rational值。也就是说,我宁愿显示0.75,而不是显示3%4。我希望这个函数的类型是Int->Rational->String。第一个Int是指定最大小数位数,因为Rational扩展可能是非终止的 而这对我没有帮助。在哪里可以找到此功能?您可以创建它。虽然不优雅,但能做到: import Numeric import Data.Ratio display :: Int -> Rational -> String display n x = (sho
Rational
值。也就是说,我宁愿显示0.75,而不是显示3%4
。我希望这个函数的类型是Int->Rational->String
。第一个Int
是指定最大小数位数,因为Rational
扩展可能是非终止的
而这对我没有帮助。在哪里可以找到此功能?您可以创建它。虽然不优雅,但能做到:
import Numeric
import Data.Ratio
display :: Int -> Rational -> String
display n x = (showFFloat (Just n) $ fromRat x) ""
以下是不使用浮动的任意精度解决方案:
导入数据。比率
显示::Int->Rational->String
显示len rat=(如果num<0,则为“-”else”“)+(显示d(“.“++获取len(下一步)))
哪里
(d,next)=abs num`quotRem`den
num=分子鼠
den=分母鼠
go 0=“”
走x=让(d,next)=(10*x)`quotRem`den
在节目d中(下一步)
可重复使用的任意精度版本:
我知道我以前见过一个函数,它以一种更容易检查的方式将有理数转换为数字(也就是说,这使得数字开始重复的位置非常清楚),但我现在似乎找不到它。在任何情况下,这并不难写,如果这被证明是一种需要;您只需编写通常的长除法算法,并查看您已经完成的除法。这是我几周前编写的一个除法。您可以指定所需的小数位数(正确舍入),或者只传递Nothing
,在这种情况下,它将打印完整精度,包括标记重复的小数
module ShowRational where
import Data.List(findIndex, splitAt)
-- | Convert a 'Rational' to a 'String' using the given number of decimals.
-- If the number of decimals is not given the full precision is showed using (DDD) for repeating digits.
-- E.g., 13.7/3 is shown as \"4.5(6)\".
showRational :: Maybe Int -> Rational -> String
showRational (Just n) r =
let d = round (abs r * 10^n)
s = show (d :: Integer)
s' = replicate (n - length s + 1) '0' ++ s
(h, f) = splitAt (length s' - n) s'
in (if r < 0 then "-" else "") ++ h ++ "." ++ f
-- The length of the repeating digits is related to the totient function of the denominator.
-- This means that the complexity of computing them is at least as bad as factoring, i.e., it quickly becomes infeasible.
showRational Nothing r =
let (i, f) = properFraction (abs r) :: (Integer, Rational)
si = if r < 0 then "-" ++ show i else show i
decimals f = loop f [] ""
loop x fs ds =
if x == 0 then
ds
else
case findIndex (x ==) fs of
Just i -> let (l, r) = splitAt i ds in l ++ "(" ++ r ++ ")"
Nothing -> let (c, f) = properFraction (10 * x) :: (Integer, Rational) in loop f (fs ++ [x]) (ds ++ show c)
in if f == 0 then si else si ++ "." ++ decimals f
模块ShowRational在哪里
导入数据列表(findIndex,splitAt)
--|使用给定的小数位数将“有理数”转换为“字符串”。
--如果未给出小数位数,则使用(DDD)表示重复数字的完整精度。
--例如,13.7/3显示为“4.5(6)”。
showRational::可能是Int->Rational->String
showRational(Just n)r=
设d=圆形(abs r*10^n)
s=显示(d::整数)
s'=复制(n-长度s+1)'0'+s
(h,f)=在(长度s'-n)s'处拆分
在(如果r<0,则“-”else“)++h++++”中
--重复数字的长度与分母的toticent函数有关。
--这意味着计算它们的复杂性至少和因子分解一样糟糕,也就是说,它很快变得不可行。
showr=
设(i,f)=性质分数(absr)::(整数,有理数)
si=如果r<0,则“-”++显示i,否则显示i
小数点f=循环f[]”
循环x fs ds=
如果x==0,则
ds
其他的
案例findIndex(x==)fs的
Just i->let(l,r)=在l++“(“++r++”)中拆分i ds
Nothing->let(c,f)=properFraction(10*x)::(整数,有理数)在循环f(fs++[x])(ds++show c)
如果f==0,则si else si++“+++小数点f
导入数据。列表为L
导入数据。比率
显示::(积分i,显示i)=>Int->Ratio i->String
显示len rat=(如果num<0,则“-”else“)++显示ip+++”++L.取len(go(abs num-ip*den))
哪里
num=分子鼠
den=分母鼠
ip=abs编号'quot'den
go 0=“”
go x=显示d(下一步)
哪里
(d,next)=(10*x)`quotRem`den
使用Numeric.fromRat
转换为realfoat
,然后使用Numeric.show*float
函数显示浮点值,这不是一个选项吗?当您最后只需要十进制近似值时,您确定需要Rational
?十进制近似值只是为了使调试更容易。我想要高达数千位的准确度。如果没有人提供标准的库解决方案,我会接受这一点。
module ShowRational where
import Data.List(findIndex, splitAt)
-- | Convert a 'Rational' to a 'String' using the given number of decimals.
-- If the number of decimals is not given the full precision is showed using (DDD) for repeating digits.
-- E.g., 13.7/3 is shown as \"4.5(6)\".
showRational :: Maybe Int -> Rational -> String
showRational (Just n) r =
let d = round (abs r * 10^n)
s = show (d :: Integer)
s' = replicate (n - length s + 1) '0' ++ s
(h, f) = splitAt (length s' - n) s'
in (if r < 0 then "-" else "") ++ h ++ "." ++ f
-- The length of the repeating digits is related to the totient function of the denominator.
-- This means that the complexity of computing them is at least as bad as factoring, i.e., it quickly becomes infeasible.
showRational Nothing r =
let (i, f) = properFraction (abs r) :: (Integer, Rational)
si = if r < 0 then "-" ++ show i else show i
decimals f = loop f [] ""
loop x fs ds =
if x == 0 then
ds
else
case findIndex (x ==) fs of
Just i -> let (l, r) = splitAt i ds in l ++ "(" ++ r ++ ")"
Nothing -> let (c, f) = properFraction (10 * x) :: (Integer, Rational) in loop f (fs ++ [x]) (ds ++ show c)
in if f == 0 then si else si ++ "." ++ decimals f
import Data.List as L
import Data.Ratio
display :: (Integral i, Show i) => Int -> Ratio i -> String
display len rat = (if num < 0 then "-" else "") ++ show ip ++ "." ++ L.take len (go (abs num - ip * den))
where
num = numerator rat
den = denominator rat
ip = abs num `quot` den
go 0 = ""
go x = shows d (go next)
where
(d, next) = (10 * x) `quotRem` den