Jea*_*ouX 7 floating-point formatting haskell scientific-notation floating-point-precision
是否存在提供工程符号格式(如String)的现有Haskell函数?
如果没有,我读到printf可以通过添加实例来扩展PrintfArg.你相信这是一个很好的解决方案吗?
通过工程符号,我的意思是指数符号,其指数是3的倍数.
经过一番研究,我设法得到我想要的东西。通过几个步骤即可获得工程格式的功能:
1. 分离指数和尾数
有必要将指数与尾数分开。该函数decodeFloat(由 提供base)对浮点数进行解码并返回尾数和2 次幂的指数(mant2 * 2 ^ ex2)。
2. 获取以正确基数表示的尾数和指数
需要进行10的幂转换。这就是这个函数的作用。
decompose :: Double -> (Double,Int)
decompose val = if mant2 > 0
then (mant10,ex10)
else (-mant10,ex10)
where
(mant2,ex2) = decodeFloat val
res = logBase 10 (fromIntegral (abs mant2)::Double) + logBase 10 (2 ** (fromIntegral ex2::Double))
ex10 = floor res
mant10 = 10**(res - (fromIntegral ex10::Double))
Run Code Online (Sandbox Code Playgroud)
3. 将指数设置为3的倍数
该函数ingen测试指数整数除法的结果,并对尾数和指数进行调整。
ingen :: Double -> (Double,Int)
ingen val
| mod ex 3 == 0 = (mant,ex)
| mod ex 3 == 1 = (mant*10,ex-1)
| mod ex 3 == 2 = (mant*100,ex-2)
where
(mant,ex) = decompose val
Run Code Online (Sandbox Code Playgroud)
以下是一些转换:
Prelude> ingen 10e7
(99.99999999999979,6)
Prelude> ingen 10e-41
(100.0,-42)
Prelude> ingen (-72364e81)
(-72.36399999999853,84)
Run Code Online (Sandbox Code Playgroud)
我使用 QuickCheck 对大范围和大量的值进行了一些测试。尽管值差异非常小(由于精度而在计算过程中四舍五入?),但转换似乎运行良好。
然而,还应该进行另一项验证。
如果您发现这些功能有错误或有改进,请分享。