scalabook
Евклидово кольцо
Формальное определение
Евклидово кольцо — это кольцо НОД, которое также поддерживает евклидово деление (например, поэтапное или целочисленное деление).
Формально евклидовы кольца определяют евклидову функцию f
такую, что для любого x
и y
в A
,
если y
ненулевое, то существуют q
и r
(частное и остаток) такие, что a = b*q + r
и r = 0
или f(r) < f(b)
.
Для целых чисел обычно f
- это функция абсолютного значения.
EuclideanRing[A]
добавляет следующие операции:
quot
(/~
,a /~ b
): частное (евклидово деление)mod
(%
,a % b
): остаток
В целых числах евклидово частное и остаток соответствуют делению с остатком;
однако знак результата является вопросом соглашения.
Для рациональных чисел (или с плавающей запятой) a /~ b = a / b
и a % b = 0
по определению.
Помимо законов кольца НОД:
- Замыкание сложения (closure): для \(\forall x, y \in R\) выполняется \(x + y \in R\).
- Ассоциативность сложения (associativity): для \(\forall x, y, z \in R\) выполняется \((x + y) + z = x + (y + z)\).
- Существование нулевого элемента: существует \(\exists 0 \in R\) такой, что для \(\forall x \in R\) выполняется \(0 + x = x + 0 = x\)
- Обратимость сложения: для \(\forall x \in R\) существует \((-x)\) такой, что \(x + (-x) = (-x) + x = 0\)
- Коммутативность сложения (commutative): для \(\forall x, y \in R\) выполняется \(x + y = y + x\).
- Замыкание умножения (closure): для \(\forall x, y \in R\) выполняется \(x * y \in R\).
- Ассоциативность умножения (associativity): для \(\forall x, y, z \in R\) выполняется \((x * y) * z = x * (y * z)\).
- Существование единичного элемента: \(\exists 1 \in R \quad \forall x \in R \quad x * 1 = 1 * x = x\)
- Коммутативность умножения: для \(\forall x, y \in R\) выполняется \(x * y = y * x\).
- Дистрибутивность (distributivus, распределительный закон): для \(\forall x, y, z \in R\) выполняется \(x * (y + z) = x * y + x * z\) и \((x + y) * z = x * z + y * z\).
- для \(\forall x, y \in R\) выполняется \(gcd(x, y) * lcm(x, y) = x * y\).
- Ассоциативность НОД: для \(\forall x, y, z \in R\) выполняется \(gcd(gcd(x, y), z) = gcd(x, gcd(y, z))\).
- Коммутативность НОД: для \(\forall x, y \in R\) выполняется \(gcd(x, y) = gcd(y, x)\).
- Ассоциативность НОК: для \(\forall x, y, z \in R\) выполняется \(lcm(lcm(x, y), z) = lcm(x, lcm(y, z))\).
- Коммутативность НОК: для \(\forall x, y \in R\) выполняется \(lcm(x, y) = lcm(y, x)\).
должен соблюдаться закон:
b * (a /~ b) + (a % b) = a
Определение в виде кода на Scala
trait EuclideanRing[A] extends GCDRing[A]: def quot(x: A, y: A): A
def mod(x: A, y: A): A
Законы в виде кода на Scala
trait EuclideanRingLaw extends GCDRingLaw: def checkEuclideanRingLaw[A: EuclideanRing]( x: A, y: A, z: A ): ValidatedNel[String, Unit] = checkGCDRingLaw(x, y, z) combine check( EuclideanRing[A].combine( EuclideanRing[A].times( y, EuclideanRing[A].quot(x, y) ), EuclideanRing[A].mod(x, y) ) == x, "b * (a /~ b) + (a % b) = a" )
Примеры
Числа относительно сложения с 0 и умножения с 1
(Z, +, *)
given EuclideanRing[Int] with val empty: Int = 0 val one: Int = 1 def combine(x: Int, y: Int): Int = x + y def times(x: Int, y: Int): Int = x * y def gcd(x: Int, y: Int): Int = if y == 0 then x else gcd(y, x % y) def lcm(x: Int, y: Int): Int = times(x, y) / gcd(x, y) def quot(x: Int, y: Int): Int = x / y def mod(x: Int, y: Int): Int = x % y extension (a: Int) override def inverse: Int = -a
Реализация
Реализация в Spire
import spire.algebra.EuclideanRingimport spire.std.int.*
EuclideanRing.plus(15, 10)// val res0: Int = 25EuclideanRing.times(15, 10)// val res1: Int = 150EuclideanRing.pow(15, 2)// val res2: Int = 225EuclideanRing.negate(15)// val res3: Int = -15EuclideanRing.minus(15, 10)// val res4: Int = 5EuclideanRing.zero[Int]// val res5: Int = 0EuclideanRing.one[Int]// val res6: Int = 1EuclideanRing.gcd(15, 10)// val res7: Int = 5EuclideanRing.lcm(15, 10)// val res8: Int = 30EuclideanRing.equot(15, 10)// val res9: Int = 1EuclideanRing.emod(15, 10)// val res10: Int = 5EuclideanRing.equotmod(15, 10)// val res11: (Int, Int) = (1,5)
Ссылки: