Вычисление выражений по модулю n

При выполнении вычислений по модулю n с большими числами вы столкнетесь с огромными потерями производительности, например, при выполнении mod (123456789 ^ 987654321) n . Вместо этого вы должны использовать свой собственный ^ , который внутренне вычисляет mod n также для промежуточных вычислений.

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

Я начал с этого, чтобы четко показать, что я имею в виду, но мне интересно, существуют ли уже реализации этого, это кажется весьма полезным, поэтому кто-то должен был это реализовать.

module Modulo where

data Expr =
    V Integer 
  | Plus Expr Expr
  | Mult Expr Expr
  deriving (Eq, Show)

instance Num Expr where
  (+) = Plus
  (*) = Mult
  fromInteger = V

eval :: Integer -> Expr -> Integer
eval m (V i) = i `mod` m
eval m (Plus e1 e2) = (eval m e1 + eval m e2) `mod` m
eval m (Mult e1 e2) = (eval m e1 * eval m e2) `mod` m

fifteen :: Expr
fifteen = 10 + 5

test = eval 13 fifteen
7
задан Tarrasch 17 November 2011 в 14:54
поделиться