跳转到内容

Python 和 Ruby 中的数学/Ruby 中的四元数

来自 Wikibooks,开放世界中的开放书籍

正如在前一章中所见,复数是一个包含 2 个实数(由 Ruby 称为 realimag)的对象。 这是凯莱-迪克森结构 的复数。 以非常类似的方式,四元数 可以被认为是由 2 个复数组成。

注意
从历史上看,汉密尔顿 将四元数构造为实数的四元组。 这也可以在 Ruby 中完成,但将留作练习。

在以下所有内容中,cmath 将被使用,因为它会自动处理分数。 这章在某种程度上与前面的章节不同,因为它展示了如何在 Ruby 中创建全新的对象,而不是如何使用现有的对象。

四元数

[编辑 | 编辑源代码]

定义和显示

[编辑 | 编辑源代码]

四元数的定义是在一个名为 Quaternion 中找到其庇护所

class Quaternion
 
end

四元数的第一个方法 将是它的实例化

实例化

[编辑 | 编辑源代码]
       def initialize(a,b)
                @a,@b = a,b
        end

从现在起,ab(将是复数)将是四元数的 2 个属性

属性 a 和 b

[编辑 | 编辑源代码]

由于定义四元数的两个数字是复数,因此将它们称为 realimaginary 部分是不合适的。 此外,稍后在八元数中将需要另一个阶段。 因此,选择了最短的名称,它们将被称为四元数的 a 及其 b

       def a
                @a
        end
 
        def b
                @b
        end

从现在起,可以使用 q.aq.b 访问四元数 qab 部分。

为了便于使用 puts(q) 显示四元数 q,有必要为其重新定义一个方法 to_s多态性 的一个例子)。 有几种选择,但这种选择效果还不错

       def to_s
                '('+a.real.to_s+')+('+a.imag.to_s+')i+('+b.real.to_s+')j+('+b.imag.to_s+')k'
        end

为了大声朗读,最好从右到左读。 例如,a.real 表示 a 的实部q.a.real 表示 q 的 a 部分的实部

四元数的绝对值是一个(正)实数。

       def abs
                Math.hypot(@a.abs,@b.abs)
        end

四元数的共轭是另一个四元数,具有相同的模。

       def conj
                Quaternion.new(@a.conj,-@b)
        end

要添加两个四元数,只需将它们的 a 相加,并将它们的 b 相加

       def +(q)
                Quaternion.new(@a+q.a,@b+q.b)
        end

- 符号的使用是多态性的另一个例子,它允许用更简单的形式编写减法。

       def -(q)
                Quaternion.new(@a-q.a,@b-q.b)
        end

四元数的乘法 更加复杂 (!)

       def *(q)
                Quaternion.new(@a*q.a-@b*q.b.conj,@a*q.b+@b*q.a.conj)
        end

这种乘法不是交换的,可以从以下示例中检查出来

p=Quaternion.new(Complex(2,1),Complex(3,4))
q=Quaternion.new(Complex(2,5),Complex(-3,-5))
puts(p*q)
puts(q*p)

除法可以定义为:

       def /(q)
                d=q.abs**2
                Quaternion.new((@a*q.a.conj+@b*q.b.conj)/d,(-@a*q.b+@b*q.a)/d)
        end

因为它们具有相同的模数,所以四元数与其共轭的商的模数为1。

p=Quaternion.new(Complex(2,1),Complex(3,4))
 
puts((p/p.conj).abs)

最后一个例子说明了,或,这是 的一个四平方和分解

Ruby 中的四元数类

[编辑 | 编辑源代码]

完整的类在这里。

require 'cmath'
 
class Quaternion
 
        def initialize(a,b)
                @a,@b = a,b
        end
 
        def a
                @a
        end
 
        def b
                @b
        end
 
        def to_s
                '('+a.real.to_s+')+('+a.imag.to_s+')i+('+b.real.to_s+')j+('+b.imag.to_s+')k'
        end
 
        def +(q)
                Quaternion.new(@a+q.a,@b+q.b)
        end
 
        def -(q)
                Quaternion.new(@a-q.a,@b-q.b)
        end
 
        def *(q)
                Quaternion.new(@a*q.a-@b*q.b.conj,@a*q.b+@b*q.a.conj)
        end
 
        def abs
                Math.hypot(@a.abs,@b.abs)
        end
 
        def conj
                Quaternion.new(@a.conj,-@b)
        end
 
        def /(q)
                d=q.abs**2
                Quaternion.new((@a*q.a.conj+@b*q.b.conj)/d,(-@a*q.b+@b*q.a.conj)/d)
        end
 
end

如果此内容保存在名为 quaternion.rb 的文本文件中,在执行 require 'quaternion' 后,就可以对四元数进行计算。

八元数

[编辑 | 编辑源代码]

关于凯莱-迪克森构造的一个有趣的事实是,它可以被推广,例如用于八元数

定义和显示

[编辑 | 编辑源代码]

所有以下方法都将包含在一个名为 Octonion 的类中。

class Octonion
 
        def initialize(a,b)
                @a,@b = a,b
        end
 
        def a
                @a
        end
 
        def b
                @b
        end

此时,与四元数对象没有太大区别。只是对于八元数,ab 将是四元数,而不是复数。当 ab 被实例化时,Ruby 将知道它。

八元数的 to_s 方法(将其转换为字符串对象以便显示)与四元数等价,只是现在有 8 个实数要显示。

       def to_s
                '('+a.a.real.to_s+')+('+a.a.imag.to_s+')i+('+a.b.real.to_s+')j+('+a.b.imag.to_s+')k+('+b.a.real.to_s+')l+('+b.a.imag.to_s+')li+('+b.b.real.to_s+')lj+('+b.b.imag.to_s+')lk'
        end

这些数字中的第一个是第一个四元数的 a 部分的实部,也就是八元数的 a!访问 八元数的 a 部分的 a 部分的实部,需要遍历深度为 3 的二叉树

由于凯莱和迪克森,八元数计算所需的函数与四元数类似。

与四元数相同。

	def abs
		Math.hypot(@a.abs,@b.abs)
	end


	def conj
		Octonion.new(@a.conj,Quaternion.new(0,0)-@b)
	end


就像四元数一样,只需要分别添加 ab(只是现在 ab 部分是四元数)。

	def +(o)
		Octonion.new(@a+o.a,@b+o.b)
	end


	def -(o)
		Octonion.new(@a-o.a,@b-o.b)
	end


	def *(o)
		Octonion.new(@a*o.a-o.b*@b.conj,@a.conj*o.b+o.a*@b)
	end

这种乘法仍然不是可交换的,而且甚至也不是结合的!

m=Octonion.new(p,q)
n=Octonion.new(q,p)
o=Octonion.new(p,p)
puts((m*n)*o)
puts(m*(n*o))


	def /(o)
		d=1/o.abs**2
		Octonion.new((@a*o.a.conj+o.b*@b.conj)*Quaternion.new(d,0),(Quaternion.new(0,0)-@a.conj*o.b+o.a.conj*@b)*Quaternion.new(d,0))
	end

这里再次,八元数与其共轭的商的模数为1。

puts(m/m.conj)
puts((m/m.conj).abs)


Ruby 中的八元数类

[编辑 | 编辑源代码]

该文件的大小与四元数文件相差无几。

class Octonion

	def initialize(a,b)
		@a,@b = a,b
	end
	
	def a
		@a
	end
	
	def b
		@b
	end
	
	def to_s
		'('+a.a.real.to_s+')+('+a.a.imag.to_s+')i+('+a.b.real.to_s+')j+('+a.b.imag.to_s+')k+('+b.a.real.to_s+')l+('+b.a.imag.to_s+')li+('+b.b.real.to_s+')lj+('+b.b.imag.to_s+')lk'
	end
	
	def +(o)
		Octonion.new(@a+o.a,@b+o.b)
	end
	
	def -(o)
		Octonion.new(@a-o.a,@b-o.b)
	end
	
	def *(o)
		Octonion.new(@a*o.a-o.b*@b.conj,@a.conj*o.b+o.a*@b)
	end
	
	def abs
		Math.hypot(@a.abs,@b.abs)
	end
	
	def conj
		Octonion.new(@a.conj,Quaternion.new(0,0)-@b)
	end
	
	def /(o)
		d=1/o.abs**2
		Octonion.new((@a*o.a.conj+o.b*@b.conj)*Quaternion.new(d,0),(Quaternion.new(0,0)-@a.conj*o.b+o.a.conj*@b)*Quaternion.new(d,0))
	end
	

end

将其保存为 octonions.rb,任何以以下内容开头的脚本

require 'octonions'

都允许对八元数进行计算。

参考文献

[编辑 | 编辑源代码]
  • 实际上,Ruby 已经有了四元数支持,但它不是(尚未)原生的:[1];在同一个网站上,还有一个八元数的文件,与上面的文件比较起来很有趣。
  • 一本关于八元数的“最佳下载”书籍是 John Baez 的书:[2]
华夏公益教科书