我目前正在尝试使用 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# 的了解有点阻碍我。是否可以创建一个接受两个参数都是 bigints 的 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'语句。有另一种解决方案吗?
在此先感谢,请原谅我的长帖子。我只是想尽可能清楚地表达我的“挑战”。