Haskell的工程符号

Jea*_*ouX 7 floating-point formatting haskell scientific-notation floating-point-precision

是否存在提供工程符号格式(如String)的现有Haskell函数?

如果没有,我读到printf可以通过添加实例来扩展PrintfArg.你相信这是一个很好的解决方案吗?


通过工程符号,我的意思是指数符号,其指数是3倍数.

Jea*_*ouX 2

经过一番研究,我设法得到我想要的东西。通过几个步骤即可获得工程格式的功能:

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 对大范围和大量的值进行了一些测试。尽管值差异非常小(由于精度而在计算过程中四舍五入?),但转换似乎运行良好。

然而,还应该进行另一项验证。

如果您发现这些功能有错误或有改进,请分享。