在Haskell中,Floating
类和Fractional
类有什么区别?
在Haskell中,Floating
类和Fractional
类有什么区别?
Fractional
是能够表示任何有理数的类型的类(精确地或至少在一个良好的近似值)。它也可以表示其他数字,但这不重要。
从另一方面来说,它只是具有除法运算的数字类型的类别;由于它是Num
的子类,因此这意味着该类型必须包含有理数。
Floating
是在Cauchy意义下封闭于极限的数字类型的类别,即完备空间。这对于进行任何形式的微积分都是必要的。 Floating
类的方法是作为极限数学上定义的函数,即无穷和(它们是泰勒级数的部分和序列的极限)。
由于您可以将实数定义为有理数序列的极限,并且再次Floating
是Fractional
的子类,因此任何Floating
类型都能够表示(再次提醒,至少在一个良好的近似值下)任何实数。
分数
类型是不连通的。特别地,有理数
可以精确地表示所有它的(有理数)值,所以每个值只是一个“无限小的点”。你永远不能用这样的点覆盖整个实数线,也不能计算像sin
或log
这样的函数,因为这些函数的结果通常是一个非有理实数。
值得思考一下这个“相当接近”的含义。Haskell标准没有定义这个。每个浮点数代表一个实数区间的故事很好地捕捉了它。更一般地说,我们可以说:Num
/Fractional
/Floating
是表示整数/有理数/实数等价类的类型类。事实上,这些类别甚至不必是“小”的区间:特别是像Word32
或标准的Int
这样的有限类型可以用模算术的意义来理解,表现为结果如(2^70 :: Int) == 0
,即等价类是2的64次幂的倍数。
Integer
或Rational
这样的情况下,等价类实际上只包含一个元素,即数字被精确地表示。对于实数,这也是可能的,但更加棘手,它被称为精确实数算术。有一些库,如aern,可以做到这一点。分数
类型不相关*”是不是有点误导人了,因为浮点
类型的集合是分数
类型的子集(因为class Fractional a => Floating a
)?这就像说“携带DNA/RNA的东西是活的”,却忘记了病毒(它们有RNA但没有新陈代谢)。 - Willem Van Onsem分数
类型没有联系,并举了有理数
作为例子。 - leftaroundaboutFractional
和Floating
的定义可以在Prelude文档中找到:
class Num a => Fractional a where (/) :: a -> a -> a recip :: a -> a fromRational :: Rational -> a
Fractional numbers, supporting real division.
[...]
class Fractional a => Floating a where pi :: a exp :: a -> a log :: a -> a sqrt :: a -> a (**) :: a -> a -> a logBase :: a -> a -> a sin :: a -> a cos :: a -> a tan :: a -> a asin :: a -> a acos :: a -> a atan :: a -> a sinh :: a -> a cosh :: a -> a tanh :: a -> a asinh :: a -> a acosh :: a -> a atanh :: a -> a
Trigonometric and hyperbolic functions and related functions.
[...]
所以,将其翻译成英语:一个Fractional
是我可以定义除法的任何数字类型:
(/) :: Fractional a => a -> a -> a
这可能适用于浮点数,也适用于分数(其中分数有一个分子和分母)。但对于Int
来说就不是这样了,因为如果将Int
除以Int
,并不总是会产生一个Int
(虽然在计算机上进行浮点除法不是精确的,但这又是另一回事)。
Fractional
数字的一个子集是Floating
数字,其中三角函数被定义。例如,一个分数的sin
总是产生分数是不可能的:一个sin
被定义为无限序列的总和。只有在极少数情况下(如sin 0
),才能成立。基本上,在计算机上唯一可以(近似地)定义三角函数的数字是浮点数。