私は現在F#を試しています。インターネットで見つけた記事は役に立ちますが、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);;
この関数は実際には高速であることがわかりましたが、その理由は (まだ) 理解できません。おそらくそれはあまり知的な質問ではありませんが、私はまだ興味があります.
2 番目の問題は、完全数を計算するときに、9 番目の完全数 (31 のべき乗から形成される) を見つけた後に、int64 が交差する大きな数を表示できないという事実に遭遇することです。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」ステートメントを使用できません。これを行う別の解決策はありますか?
前もって感謝し、私の長い投稿を許してください。私は自分の「挑戦」をできるだけ明確に表現しようとしているだけです。