Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
F#接受两个参数为大整数的幂问题_F#_Pattern Matching_Perfect Numbers - Fatal编程技术网

F#接受两个参数为大整数的幂问题

F#接受两个参数为大整数的幂问题,f#,pattern-matching,perfect-numbers,F#,Pattern Matching,Perfect Numbers,我目前正在试验F#。互联网上的文章很有帮助,但作为一名C#程序员,我有时会遇到一些情况,我认为我的解决方案会有所帮助,但没有或只是部分帮助 因此,我对F#(很可能还有编译器的工作原理)缺乏了解,这可能是我有时完全目瞪口呆的原因 例如,我编写了一个C#程序来确定完美数。它使用了欧几里德证明的已知形式,即梅森素数2p可以形成一个完美数−1(2p−1) (其中2p-1是素数,p表示为的幂) 由于F#的帮助说明“**”可以用来计算幂,但使用浮点,因此我尝试创建一个带有位移位运算符的简单函数(我认为定义P

我目前正在试验F#。互联网上的文章很有帮助,但作为一名C#程序员,我有时会遇到一些情况,我认为我的解决方案会有所帮助,但没有或只是部分帮助

因此,我对F#(很可能还有编译器的工作原理)缺乏了解,这可能是我有时完全目瞪口呆的原因

例如,我编写了一个C#程序来确定完美数。它使用了欧几里德证明的已知形式,即梅森素数2p可以形成一个完美数−1(2p−1) (其中2p-1是素数,p表示为的幂)


由于F#的帮助说明“**”可以用来计算幂,但使用浮点,因此我尝试创建一个带有位移位运算符的简单函数(我认为定义
PowBigInt
最简单的方法是使用
if
而不是模式匹配:

let rec PowBigInt (x : bigint) (y : bigint) =  
  if y = 0I then 1I   
  else x * PowBigInt x (y - 1I) 
问题是,
bigint.Zero
是一个返回值的静态属性,但是模式只能包含(常量)文本或F#active模式。它们不能直接包含属性(或其他)调用。但是,如果您仍然喜欢
匹配
,可以在
where
子句中编写其他约束:

let rec PowBigInt (x : bigint) (y : bigint) =  
  match y with 
  | y when y = bigint.Zero -> 1I 
  | y -> x * PowBigInt x (y - 1I)
作为旁注,您可能可以使用尾部递归来提高函数的效率(其思想是,如果函数将递归调用作为最后一件事,那么可以更高效地编译它):


关于
PowBitShift
功能,我不知道为什么它会慢一些,但它肯定不能满足您的需要。使用位移位实现功率仅在基数为2时起作用。

我无法理解为什么您需要
y
成为
int64
bigint
。根据已知的最大的梅森尼编号为
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
,错误消息非常清楚地表明,您可以通过
在以下情况下使用模式匹配:

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

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

bigint 10**32


另一个选项是内联函数,使其与所有数字类型(支持所需运算符:
(*)
(-)
获取一个
,和
获取零
)一起工作)


我可能会建议按照Tomas的建议,将其设置为尾部递归。

啊,这很清楚,我还不知道您可以在模式匹配器中设置下划线。关于bigint的需要,我正在编写一个程序,它可以显示第10个(及以上)完美数,实际上不能放在64位整数(或一些人喜欢的长整数)内。您误解了某些内容。2 ^p-1应该是
bigint
,但是
int
对于
p
来说已经足够了。因此参数
y
不必是
int64
bigint
。这与
pown
具有第二个参数作为
int
的原因相同。这确实正确,我真傻。然而,第47个完美数的幂为43.112.609,现在还不知道下一个幂是什么。我发现:我的目标是编写一个程序,至少可以尝试找到所有47个完美数(希望更多,但这可能是一个彻底的尝试)@RvdV79-希望更多!非常有趣的评论。我希望我有一个妻子和一个博客来谈论:D。我需要重新表述一下我的问题,我放置的代码是不正确的,因为计算需要2的幂,我认为在1(1作为基数)上向左移动(指数部分)在我的代码中,x被值1填充,它可以被常量本身所代替。我将不得不做另一个测试,看看它是否更快。谢谢你的广泛回答托马斯,我会尝试一下。你的回答引导我找到了一个较小的错误,我也会尝试修正。原谅感谢我没有留下评论Daniel,我只是错过了你的反应。尾部递归引起了我的兴趣,但你在这里的例子帮助我越来越理解F#语言。我从你们身上学到的越多,我就变得越热情!无论如何,非常感谢你的努力Daniel,非常感谢!第一个问题很好,欢迎使用堆栈溢出!
let rec PowBigInt (x : bigint) (y : bigint) =  
  if y = 0I then 1I   
  else x * PowBigInt x (y - 1I) 
let rec PowBigInt (x : bigint) (y : bigint) =  
  match y with 
  | y when y = bigint.Zero -> 1I 
  | y -> x * PowBigInt x (y - 1I)
let PowBigInt (x : bigint) (y : bigint) =   
  // Recursive helper function that stores the result calculated so far
  // in 'acc' and recursively loops until 'y = 0I'
  let rec PowBigIntHelper (y : bigint) (acc : bigint) =
    if y = 0I then acc 
    else PowBigIntHelper (y - 1I) (x * acc)
  // Start with the given value of 'y' and '1I' as the result so far
  PowBigIntHelper y 1I
let Pow (x : int64) y = pown x y
let PowBigInt (x: bigint) y = pown x y
let rec PowBigInt x y = 
    match y with
    | _ when y = 0I -> 1I
    | _ -> x * PowBigInt x (y - 1I)
val it : System.Numerics.BigInteger =
  100000000000000000000000000000000 {IsEven = true;
                                     IsOne = false;
                                     IsPowerOfTwo = false;
                                     IsZero = false;
                                     Sign = 1;}
let rec inline PowBigInt (x:^a) (y:^a) : ^a =  
  let zero = LanguagePrimitives.GenericZero 
  let one = LanguagePrimitives.GenericOne
  if y = zero then one
  else x * PowBigInt x (y - one) 

let x = PowBigInt 10 32     //int
let y = PowBigInt 10I 32I   //bigint
let z = PowBigInt 10.0 32.0 //float