Haskells `succ` 数字(浮点数)背后的基本原理
Rationale behind Haskells `succ` on numbers (floats)
得知 Haskell 将其 succ
函数定义为加一,我感到有些惊讶:
succ :: a -> a
The successor of a value. For numeric types, succ adds 1.
尽管对于整数值,这似乎是合理的,但存在一些问题:
- 如果您定义一个只能表示 even/odd/prime/... 数字的数字系统,换句话说,一个专用类型,它是整数的子集,会怎样;
- 如果您定义了某种代表半数和全数的 "fixed-point number",在这种情况下,不会枚举所有数字;和
- 浮点数问题最严重。
首先,这意味着 [2.0 :: Float .. 3.0 :: Float]
(使用 :: Float
来确保调用没有歧义)仅包含添加到原始值的整数值,而如果使用此表达式 he/she 可能期望列表将包含两个值之间的所有浮点数;当然,这种争论更多的是关于一个人更喜欢什么。大多数程序员在这方面问题不大。
更严重的是,如果使用表达式 [2.2 :: Float .. 4.0 :: Float]
会导致 [2.2,3.2,4.2]
4.2
在这里做什么?
如果使用 +1
无法生成不同数字的浮点数(因为尾数没有足够的位来表示一个),它将无限循环。例如:
Prelude> [1e37 :: Float .. 1e37 :: Float]
[1.0e37,1.0e37,1.0e37,1.0e37,1.0e37,1^C.0e37,Interrupted.
Prelude> [1e37 :: Float .. 1e37-1 :: Float]
[1.0e37,1.0e37,1.0e37,1.0e37,1.0e37,1^C.0e37,Interrupted.
Prelude> [1e37 :: Float .. 1e37+1 :: Float]
[1.0e37,1.0e37,1.0e37,1.0e37,1.0e37,1^C.0e37,Interrupted.
Prelude> [1e37 :: Float .. pred 1e37 :: Float]
[1.0e37,1.0e37,1.0e37,1.0e37,1.0e37,1^C.0e37,Interrupted.
因此,即使列表应该为空或包含一些元素,也可以生成无限量的值。
部分论点确实有点吹毛求疵,但至少对于某些人来说,假设Haskell程序员最终会犯错误是合理的。
生成下一个可表示的浮点数不是更合理的方法吗?
这样定义 succ
的依据是什么? Float
是 Enum
的实例是否合理?
succ
函数本身的起源实际上与Haskell数据类型或枚举无关,实际上succ
函数首先出现。 succ
函数实际上是axiom of infinity which allows us to create numbers in the first place中的后继函数。它从未设计用于浮动 point/non-natural 数字,这就是您遇到此问题的原因。
为 Haskell 中的浮点类型修改 succ
函数可能是个好主意,您应该向邮件列表提交有关它的内容。尽管 Haskell 在 Haskell98 报告中已标准化,所以不要对更改语言抱有希望。
如果您熟悉 Haskell 的类型,请仅阅读以下内容 classes: 您提到了 [=10= 的不同可能用途] 函数,这就是为什么它被定义为 Enum
类型 class 的函数。因此,您可以轻松地重新绑定它以使用 newtype
.
做一些不同的事情
得知 Haskell 将其 succ
函数定义为加一,我感到有些惊讶:
succ :: a -> a
The successor of a value. For numeric types, succ adds 1.
尽管对于整数值,这似乎是合理的,但存在一些问题:
- 如果您定义一个只能表示 even/odd/prime/... 数字的数字系统,换句话说,一个专用类型,它是整数的子集,会怎样;
- 如果您定义了某种代表半数和全数的 "fixed-point number",在这种情况下,不会枚举所有数字;和
- 浮点数问题最严重。
首先,这意味着 [2.0 :: Float .. 3.0 :: Float]
(使用 :: Float
来确保调用没有歧义)仅包含添加到原始值的整数值,而如果使用此表达式 he/she 可能期望列表将包含两个值之间的所有浮点数;当然,这种争论更多的是关于一个人更喜欢什么。大多数程序员在这方面问题不大。
更严重的是,如果使用表达式 [2.2 :: Float .. 4.0 :: Float]
会导致 [2.2,3.2,4.2]
4.2
在这里做什么?
如果使用 +1
无法生成不同数字的浮点数(因为尾数没有足够的位来表示一个),它将无限循环。例如:
Prelude> [1e37 :: Float .. 1e37 :: Float]
[1.0e37,1.0e37,1.0e37,1.0e37,1.0e37,1^C.0e37,Interrupted.
Prelude> [1e37 :: Float .. 1e37-1 :: Float]
[1.0e37,1.0e37,1.0e37,1.0e37,1.0e37,1^C.0e37,Interrupted.
Prelude> [1e37 :: Float .. 1e37+1 :: Float]
[1.0e37,1.0e37,1.0e37,1.0e37,1.0e37,1^C.0e37,Interrupted.
Prelude> [1e37 :: Float .. pred 1e37 :: Float]
[1.0e37,1.0e37,1.0e37,1.0e37,1.0e37,1^C.0e37,Interrupted.
因此,即使列表应该为空或包含一些元素,也可以生成无限量的值。
部分论点确实有点吹毛求疵,但至少对于某些人来说,假设Haskell程序员最终会犯错误是合理的。
生成下一个可表示的浮点数不是更合理的方法吗?
这样定义 succ
的依据是什么? Float
是 Enum
的实例是否合理?
succ
函数本身的起源实际上与Haskell数据类型或枚举无关,实际上succ
函数首先出现。 succ
函数实际上是axiom of infinity which allows us to create numbers in the first place中的后继函数。它从未设计用于浮动 point/non-natural 数字,这就是您遇到此问题的原因。
为 Haskell 中的浮点类型修改 succ
函数可能是个好主意,您应该向邮件列表提交有关它的内容。尽管 Haskell 在 Haskell98 报告中已标准化,所以不要对更改语言抱有希望。
如果您熟悉 Haskell 的类型,请仅阅读以下内容 classes: 您提到了 [=10= 的不同可能用途] 函数,这就是为什么它被定义为 Enum
类型 class 的函数。因此,您可以轻松地重新绑定它以使用 newtype
.