F#中的共同素数值

时间:2016-10-21 15:43:36

标签: python f#

我是一个处理琐碎问题的F#新手。如何检查两个整数是否是共同素数?我发现this pythonic方法非常有趣,恕我直言,优雅。我试图用F#翻译它,没有财富。我想这主要是因为我缺乏经验。

无论如何,这是我迄今为止的“最佳”尝试:

let prime (x, y) =                                          
  if y <> 0 then
      (x, y) <| (y, x % y)
  else 
      x;; 

应该产生,即

prime 23 13;;
- : bool = true

显然,它不起作用。在F#中解决这个问题的最佳方法是什么?我来自R编程,需要完全不同的思维形式。

2 个答案:

答案 0 :(得分:8)

几乎是链接的python代码的直接翻译。

首先,我们需要使用递归定义{{​​1}}函数作为&#34;循环构造&#34;而不是python而(FP更多&#34;面向递归&#34;)

gcd

只留下let rec gcd = function | x, 0 -> x | x, y -> gcd (y, x % y) 函数来定义哪些可以在 pointfree样式中轻松完成,方法是将先前的coprime函数与1的相等部分应用程序组合在一起

gcd

功能与以下相同:

let coprime = gcd >> (=) 1

除此之外我们可以通过一些调整来使代码更通用(关于数字类型),虽然我不确定它是否值得 (例如,当操纵bigint时,人们可能更喜欢使用let coprime (x, y) = gcd (x, y) = 1

BigInteger.GreatestCommonDivisor

@Henrik Hansen回答这里是一个更新版本,用active pattern来简化可读性并提取常见行为

open LanguagePrimitives

let inline gcd (x, y) =
  // we need an helper because inline and rec don't mix well
  let rec aux (x, y) =
    if y = GenericZero
    then x
    else aux (y, x % y)
  aux (x, y)

// no pointfree style, only function can be inlined not values
let inline coprime (x, y) = gcd (x, y) = GenericOne

答案 1 :(得分:6)

仅适用于这项运动:这是使用欧几里得算法的减法版本的版本。不像Sehnsuchts那样优雅地使用分裂风格,而且可能没那么高效:

let rec areCoPrimes a b =
    match a, b with
    | a, b when a < 0 -> areCoPrimes -a b
    | a, b when b < 0 -> areCoPrimes a -b
    | 0, b  -> false
    | a, 0 -> false
    | a, b when a = b -> a = 1
    | a, b when a > b -> areCoPrimes (a - b) b
    | a, b when a < b -> areCoPrimes a (b - a)

欧几里德肉是最后三场比赛,而前四场则是小于或等于零的值。