Проблемы с питанием F #, которые принимают оба аргумента как важные

В настоящее время я экспериментирую с 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);;

Оказывается, эта функция на самом деле быстрее, но я (пока) не могу понять, почему. Возможно, это менее интеллектуальный вопрос, но мне все же любопытно.

Тогда возникает второй вопрос: при вычислении совершенных чисел вы сталкиваетесь с тем фактом, что int64 не может отображать пересечение больших чисел после нахождения 9-го совершенного числа (которое формируется из степени 31). Я пытаюсь выяснить, можете ли вы использовать объект BigInteger (или тип bigint), но здесь мои знания F # немного блокируют меня.Можно ли создать функцию управления мощностью, которая принимает оба аргумента как bigint?

В настоящее время у меня есть это:

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'. Есть ли другое решение для этого?

Заранее спасибо и простите за мой длинный пост. Я лишь пытаюсь как можно яснее выразить свои «проблемы».

11
задан RvdV79 8 January 2015 в 19:13
поделиться