В настоящее время я экспериментирую с F #. Статьи, найденные в Интернете, полезны, но, как программист на С#, я иногда сталкиваюсь с ситуациями, когда я думал, что мое решение поможет, но это не помогло или частично помогло.
Таким образом, моя нехватка знаний о F # (и, скорее всего, как работает компилятор), вероятно, является причиной того, что иногда я часто ошеломлен.
Например, я написал программу С# для определения совершенных чисел. Он использует известную форму доказательства Евклидов, что идеальное число может быть образовано из Первого Мерсенна 2p-1 (2p-1) (где 2p-1 является простым, а p обозначается как степень).
Поскольку с помощью F # указано, что '**' может использоваться для вычисления мощности, но использует плавающие точки, я попытался создать простую функцию с оператором бит-сдвига (< < <) (обратите внимание, что я 'отредактируйте этот код для указания необходимости):
let PowBitShift (y:int32) = 1 <<< y;;
Однако при запуске теста и поиске улучшений производительности я также попытался использовать форму, которую я помню, используя Миранду (язык функционального программирования), который использует рекурсию и шаблонный шаблон для вычисления мощности. Основное преимущество заключается в том, что я могу использовать переменную 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?
В настоящее время у меня есть это:
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.
Но шаблонный шаблон не может использовать оператор "когда". Есть ли другое решение для этого?
Спасибо заранее, и прошу простить мой длинный пост. Я только пытаюсь выразить свои "вызовы" как можно яснее.