我目前正在试验F#。该文章,在因特网上找到的都是有用的,但作为一个C#程序员,我有时候会遇到的情况下,我认为我的解决方法会有所帮助,但它并没有或只是部分地帮助。

所以我的知识缺乏的#(和最可能的是,如何编译工作)是可能的原因,我为什么完全大吃一惊的时候。

例如,我写了一C#程序,以确定完善的数字。它使用的已知形式的Euclids证明,一个完美的数量可以形成一个总理梅森2p−1(2p−1)(其中2p-1是总理,以及p被表示为电力)。

由于帮助的F#国'**'可用于计算权力,但使用浮点,我试图建立一个简单的功能与bitshift操作员(<<<)(注意,我编辑这个代码指出需要):

 let PowBitShift (y:int32) = 1 <<< y;;

然而,当在运行测试,并寻找改进性能,我也尝试了一种形式,我记得从使用米兰达(a功能的程序语言,也),其中采用递归和一个模式匹配计算的权力。主要好处是,我可以使用的变量 y 作为64位整数,这是不可能的标准bitshift操作员。

    let rec Pow (x : int64) (y : int64) = 
    match y with
        | 0L -> 1L
        | y -> x * Pow x (y - 1L);;

事实证明,这一功能是实际上更快地,但我无法(尚未)了解原因为何。也许这是一个不知识产权的问题,但我仍然感到好奇。

该秒的问题将是,在计算完美的数字,你碰到的事实,int64无法显示大的数字过境后发现第9perfectnumber(其形成的力量31).我试图找出是否可以使用BigInteger对象(或bigint类型)之后,但在这里我的知识F#是阻止我一个位。是否有可能创建一个powerfunction其接受这两个论点可以bigints?

我现在有这样的:

let rec PowBigInt (x : bigint) (y : bigint) = 
    match y with
        | bigint.Zero -> 1I
        | y -> x * Pow x (y - 1I);;

但它抛出一个错误,bigint。零没有定义。所以我在做的事情是错误的。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.    

但一个模式匹配器无法使用'当'的发言。是否有另一种解决方案做到这一点?

在此先感谢,并请原谅我的长员额。我只想表达我的'挑战'明确的,因为我可以。

有帮助吗?

解决方案

我不明白为什么你需要的 y 是一个 int64bigint.根据 这个链接, 最大的称梅森数是一个 p = 43112609, ,哪里 p 确实是内部范围的 int.

具有 y 作为一个整数,可以使用的标准操作员 pown : ^T -> int -> ^T 而不是因为:

let Pow (x : int64) y = pown x y
let PowBigInt (x: bigint) y = pown x y

关于你的问题的模式匹配 bigint, 错误消息表示相当清楚,可以使用模式匹配的通过 when 卫兵:

let rec PowBigInt x y = 
    match y with
    | _ when y = 0I -> 1I
    | _ -> x * PowBigInt x (y - 1I)

其他提示

我认为定义PowBigInt的最简单方法是使用if而不是模式匹配: 通用标签

问题在于bigint.Zero是返回值的静态属性,但是模式只能包含(恒定)文字或F#活动模式。它们不能直接包含属性(或其他)调用。但是,如果您仍然喜欢where,则可以在match子句中编写其他约束: 通用标签

作为旁注,您可以使用 tail-recursion 使功能更高效(其思想是,如果函数将递归调用作为最后一件事,则可以对其进行更多编译有效): 通用标签

关于PowBitShift函数-我不确定为什么它要慢一些,但是它绝对不能满足您的需求。仅当基数为2时,才能使用移位实现功率。

您不需要创建Pow函数。 (**)运算符对于bigint-> int-> bigint有重载。 只有第二个参数应该是整数,但是对于您的情况,我认为这不是问题。 尝试

bigint 10 ** 32 ;; 通用标签

另一种选择是内联函数,以便它与所有数字类型(支持必需的运算符:(*)(-)get_Oneget_Zero)一起使用。 通用标签

我可能建议像Tomas推荐的那样将其尾部递归。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top