跳轉到內容

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]
華夏公益教科書