【发布时间】:2012-01-11 12:02:03
【问题描述】:
我目前正在尝试使用 F#。在 Internet 上找到的文章很有帮助,但作为 C# 程序员,我有时会遇到一些情况,我认为我的解决方案会有所帮助,但它没有或只是部分帮助。
所以我对 F# 的了解(很可能是编译器的工作原理)可能是我有时完全惊呆的原因。
例如,我编写了一个 C# 程序来确定完美数。它使用已知形式的欧几里得证明,完美数可以由梅森素数 2p-1(2p-1) 形成(其中 2p-1 是素数,p 表示为的幂)。
由于 F# 的帮助表明 '**' 可用于计算幂,但使用浮点数,因此我尝试使用位移运算符 (
let PowBitShift (y:int32) = 1 <<< y;;
但是,在运行测试并寻求性能改进时,我还尝试了一种我记得使用 Miranda(也是一种函数式编程语言)的形式,它使用递归和模式匹配器来计算功率。主要好处是我可以将变量 y 用作 64 位整数,这是标准位移运算符无法实现的。
let rec Pow (x : int64) (y : int64) =
match y with
| 0L -> 1L
| y -> x * Pow x (y - 1L);;
事实证明,这个函数实际上更快,但我(还)不明白其中的原因。也许这是一个不那么理智的问题,但我仍然很好奇。
那么第二个问题是,在计算完美数时,您会遇到这样一个事实,即 int64 无法显示在找到第 9 个完美数(由 31 的幂形成)后交叉的大数。我试图找出你是否可以使用 BigInteger 对象(或 bigint 类型),但在这里我对 F# 的了解有点阻碍我。是否可以创建一个同时接受两个参数为 bigint 的 powerfunction?
我目前有这个:
let rec PowBigInt (x : bigint) (y : bigint) =
match y with
| bigint.Zero -> 1I
| y -> x * Pow x (y - 1I);;
但它会抛出一个错误,即 bigint.Zero 未定义。所以我在那里也做错了什么。 0I 不被接受作为替代品,因为它给出了这个错误:
Non-primitive numeric literal constants cannot be used in pattern matches because they
can be mapped to multiple different types through the use of a NumericLiteral module.
Consider using replacing with a variable, and use 'when <variable> = <constant>' at the
end of the match clause.
但是模式匹配器不能使用'when'语句。有其他解决方案吗?
先谢谢了,请原谅我的长帖。我只是想尽可能清楚地表达我的“挑战”。
【问题讨论】:
-
第一个问题很好,欢迎来到 Stack Overflow!
标签: f# pattern-matching perfect-numbers