用 Raku 做数学
Sets
Raku 包括 Set 数据类型,以及对大多数 set 操作的支持。并集和交集不仅是原生操作,它们使用自然符号 ∩
和 ∪
。例如,此代码将检查有限数量集的集算术的基本定律:
my @arbitrary-numbers = ^100;
my \U = @arbitrary-numbers.Set;
my @sets;
@sets.push: Set.new( @arbitrary-numbers.pick( @arbitrary-numbers.elems.rand)) for @arbitrary-numbers;
my (@union, @intersection);
for @sets -> $set {
@union.push: $set ∩ $set === $set;
@intersection.push: $set ∪ $set === $set;
}
say "Idempotent union is ", so @union.all;
# OUTPUT: «Idempotent union is True»
say "Idempotent intersection is ", so @intersection.all;
# OUTPUT: «Idempotent intersection is True»
my (@universe, @empty-set, @id-universe, @id-empty);
for @sets -> \A {
@universe.push: A ∪ U === U;
@id-universe.push: A ∩ U === A;
@empty-set.push: A ∩ ∅ === ∅;
@id-empty.push: A ∪ ∅ === A;
}
say "Universe dominates ", so @universe.all; # OUTPUT: «Universe dominates True»
say "Empty set dominates ", so @empty-set.all; # OUTPUT: «Empty set dominates True»
say "Identity with U ", so @id-universe.all; # OUTPUT: «Identity with U True»
say "Identity with ∅ ", so @id-empty.all; # OUTPUT: «Identity with ∅ True»
在这个使用 Raku 已经定义的空集的代码中,我们不仅检查集合代数中的等式是否成立,我们还通过无符号变量和集合运算符的 Unicode 形式使用表达式。尽可能接近原始形式; 例如,A ∪ U === U
,除了使用值标识运算符 <===> 与维基百科条目中的实际数学表达式非常接近。
我们甚至可以测试摩根定律,如下面的代码所示:
my @alphabet = 'a'..'z';
my \U = @alphabet.Set;
sub postfix:<⁻>(Set $a) { U ⊖ $a }
my @sets;
@sets.push: Set.new( @alphabet.pick( @alphabet.elems.rand)) for @alphabet;
my ($de-Morgan1,$de-Morgan2) = (True,True);
for @sets X @sets -> (\A, \B){
$de-Morgan1 &&= (A ∪ B)⁻ === A⁻ ∩ B⁻;
$de-Morgan2 &&= (A ∩ B)⁻ === A⁻ ∪ B⁻;
}
say "1st De Morgan is ", $de-Morgan1;
say "2nd De Morgan is ", $de-Morgan2;
我们声明 - 作为补语运算,它计算通用集U和我们集之间的对称差⊖。一旦宣布这一点,就可以比较容易地表达诸如A和B的并集 (A ∪ B)⁻
的补集,其符号与原始数学符号非常接近。
算术
Raku 可以使用不同的数据类型进行算术运算。 Num,Rat 和 Complex 都可以在操作加法,减法,乘法和除法下作为场运行。等效的数学领域是:
Raku class | Field |
---|---|
C | ℚ |
C | ℝ |
C | ℂ |
Int
s 虽然在技术上与 Z 相对应,但它并不是真正的数学领域,因为它们不是在四个算术运算下关闭的,并且整数不满足同一性公理。但是,如果使用整数除法 div
,它们的操作将始终产生其他整数;但是,如果使用 /
,通常结果将是 Rat。
此外,Int
可以进行无限精度算术(或者至少在存储器允许的情况下无限制;还可以发生数字溢出(Numeric overflow
)),如果数字太大则不会回落到 Num:
my @powers = 2, 2 ** * ... Inf; say @powers[4].chars; # OUTPUT: «19729»
同样严格地说,行为类似于数学领域的 Rational 类是 FatRat。出于效率原因,当数字足够大或者分子和分母之间存在很大差异时,操作 Rats
时会回落到 Num
。 FatRat
可以使用任意精度,与默认的 Int
类相同。
生态系统中的某些模块可以使用数学方法处理其他数据类型:
- Math::Matrix 操作矩阵字段。
- Math::Quaternion 操作四元数字段,这是复数的推广。
- Math::Polynomial 与多项式一起使用,并且能够用它们进行简单的算术运算。
- Math::Symbolic,用于符号数学
数字会自动变为其实际表示的数字类型:
.^name.say for (4, ⅗, 1e-9, 3+.1i); # OUTPUT: «IntRatNumComplex»
这也使算术运算最适合特定类型
say .33-.22-.11 == 0; # OUTPUT: «True»
在这儿,所有数字都被解释为 Rat
s,这使得操作准确。通常,大多数语言会将它们解释为浮点数,
say .33.Num -.22.Num - .11.Num; # OUTPUT: «1.3877787807814457e-17»
对于这样的情况,Raku 还包括一个近似相等的运算符(approximately equal
),≅
say .33.Num -.22.Num - .11.Num ≅ 0; # OUTPUT: «True»
序列
序列是允许重复的对象的枚举集合,也是 Raku 中称为 Seq 的第一类数据类型。 Seq
能够表示无限序列,如自然数:
my \𝕟 = 1,2 … ∞;
say 𝕟[3];# OUTPUT: «4»
无限序列使用 ∞,Inf
或 *
(Whatever)作为终止符。 ...
是列表生成器,只要插入第一个数字,它实际上可以理解算术和几何级数:
say 1,5,9 … * > 100;
# OUTPUT: «(1 5 9 13 17 21 25 29 33 37 41 45 49 53 57 61 65 69 73 77 81 85 89 93 97 101)»
say 1,3,9 … * > 337; # OUTPUT: «(1 3 9 27 81 243 729)»
当生成的数字大于 100 时,第一个序列将终止; 第二个序列,当它大于 337 时,是几何级数。
可以使用任意生成器的事实可以很容易地生成像 Fibonacci 这样的序列:
say 1,1, * + * … * > 50;# OUTPUT: «(1 1 2 3 5 8 13 21 34 55)»
事实上,我们可以通过这种方式计算黄金比例的近似值:
my @phis = (2.FatRat, 1 + 1 / * ... *);
my @otherphi = (1 - @phis[200], 1 + 1 / * ... *);
say @otherphi[^10, |(20, 30 ... 100)];# OUTPUT:
# «((-0.61803398874989484820458683436563811772030918
# -0.61803398874989484820458683436563811772030918
# -0.61803398874989484820458683436563811772030918
# -0.61803398874989484820458683436563811772030918
# -0.61803398874989484820458683436563811772030918
# -0.618033…»
Math::Sequences 模块包含许多已为你定义的数学序列。它定义了百科全书中的许多序列,其中一些序列的原始名称,如 ℤ 或 ℝ。
一些集合运算符也对序列进行操作,它们可用于查明对象是否是其中的一部分:
say 876 ∈ (7,14 … * > 1000) ; # OUTPUT: «False»
在这种特殊情况下,我们可以看出 876
是否是 7 的直接倍数,但同样的原理适用于使用复杂发生器的其他序列。我们也可以使用集合包含运算符:
say (55,89).Set ⊂ (1,1, * + * … * > 200); # OUTPUT: «True»
虽然它没有考虑到它是否实际上是一个子序列,但这里只是存在两个元素;集合没有顺序,即使您没有将子序列显式地转换为Set或显式地将其转换为Seq,它也会被强制转换为包含运算符的应用程序。
数学常数
Raku 已经包含了一组数学常量作为核心的一部分。
say π; # OUTPUT: «3.141592653589793»
say τ; # Equivalent to 2π; OUTPUT: «6.283185307179586»
say 𝑒; # OUTPUT: «2.718281828459045»
它们的拉丁名字 e
, pi
和 tau
也是可得的, 具有相同的值 (尽管 𝑒
在 MoarVM 外面访问不了).
Math::Constants 模块包括一系列额外的物理和数学常数,例如前面提到的黄金比率 φ
或普朗克常数 ℎ
。
由于 Raku 允许定义使用 Unicode 字形的变量,以及没有任何类型的 sigil 的变量和常量名称,因此使用概念的实际数学名称来尽可能地命名它们被认为是一种好的做法。