大一學(xué)這個(gè)解析幾何的時(shí)候就想著用一門語言把里面的算法都實(shí)現(xiàn)了,可是一直拖拖拉拉的處于未完工的狀態(tài)。
這就是我的書(我的字怎么這么丑)
實(shí)現(xiàn)起來其實(shí)算法都在書里面,就是你沒有寫過大項(xiàng)目,所以不知道咋寫。那第一個(gè)思路就是找找有沒有現(xiàn)成的書,翻著看。就找到一本,我還找不到電子版的。
書中的目錄可以看,就用的4個(gè)庫,因?yàn)槎际瞧胀ǖ牡讓铀惴ā?span style="text-align: center;">所以這些庫就可以實(shí)現(xiàn),第一個(gè)是數(shù)組,第二個(gè)是科學(xué)計(jì)算,第三個(gè)是繪圖,第四個(gè)數(shù)值運(yùn)算的庫。
然后里面大部分是矩陣運(yùn)算,看著沒有高等代數(shù)難。
然后我還找到一個(gè)關(guān)于解析幾何的GitHub庫,就是我認(rèn)為不錯(cuò)的庫。
https://github.com/jan-mue/geometer
簡單的介紹
pip install geometer
pip安裝一下就行,當(dāng)然也會(huì)安裝一些依賴庫,安裝就行。
https://geometer.readthedocs.io/en/stable/
這個(gè)項(xiàng)目也是提供了一個(gè)參考的文檔來學(xué)習(xí)。
你可以這樣的創(chuàng)建一個(gè)最基礎(chǔ)的點(diǎn)
可以看一下類定義
實(shí)現(xiàn)的源碼
點(diǎn)的定義
內(nèi)部的初始化類
大部分都是Numpy的庫,這些函數(shù)都沒有用過,所以得先看看Numpy的庫
https://numpy.org/doc/stable/user/whatisnumpy.html
文檔在此
https://github.com/search?l=Jupyter+Notebook&q=numpy&type=Repositories
在Github里面找一下Numpy相關(guān)的庫。
https://github.com/rougier/numpy-100
找到一個(gè)合適的庫,100道題
我們傳統(tǒng)的Python代碼實(shí)現(xiàn)的逐元素向乘
C系語言版本
Numpy的運(yùn)算是一種叫廣播的機(jī)制:廣播是用于描述操作的隱式逐元素行為的術(shù)語;一般而言,在 NumPy 中,所有操作,不僅是算術(shù)運(yùn)算,還有邏輯、按位、函數(shù)等,都以這種隱式的逐元素方式表現(xiàn),即它們進(jìn)行廣播。此外,在上面的例子中,可以是相同形狀的多維數(shù)組,a
也b
可以是標(biāo)量和數(shù)組,甚至是兩個(gè)不同形狀的數(shù)組,前提是較小的數(shù)組可以“擴(kuò)展”為較大的數(shù)組的形狀結(jié)果廣播是明確的。
維度稱為軸
里面的常見的幾個(gè)方法
一個(gè)列表也可以成為最簡單的一個(gè)數(shù)組元素
接下來我們使用Python實(shí)現(xiàn)一下自己的矩陣類及其計(jì)算:
我們就寫兩個(gè)腳本先,main這個(gè)文件是測試腳本
直接放一段我寫的代碼看看,在文章的后面會(huì)有完整的實(shí)現(xiàn)
這里說一下編寫這個(gè)東西的一些考量,因?yàn)橄蛄孔罨镜臇|西就是一個(gè)點(diǎn),所以用列表當(dāng)參數(shù)。因?yàn)橄旅娴姆椒ㄒ亩际且?,萬一進(jìn)來的時(shí)候不是引用,用list()來復(fù)制一下,確保傳參數(shù)無誤。
def __repr__(self):
return "Vector({})".format(self._values)
def __str__(self):
return "({})".format(", ".join(e for e in self._values))
在一個(gè)類制作出來的時(shí)候,就該考慮,機(jī)器層面的展示和面向人類展示方法 ,引入自帶的魔法方法,定義一下,然后__str__里面使用了一下for。
為了編寫更有專業(yè)味道的代碼,這里進(jìn)行了改進(jìn),使用了迭代器。你看參數(shù)的調(diào)用樣子,也需要注意使用了斷言判斷向量的維數(shù)在運(yùn)算的時(shí)候是不是同維的。
就是這樣的就可以
測試文件,提前寫這里
實(shí)現(xiàn)加法
加法運(yùn)算更加通俗的理解
擴(kuò)展三維
證明
數(shù)乘
普遍理解
證明
一些性質(zhì)(在類中已經(jīng)全部實(shí)現(xiàn) )
證明
源碼在此:
class Vector:
def __init__(self, lst):
self._values = list(lst)
# 此處是一個(gè)引用,復(fù)制一下
# 為了處理這個(gè)地方的私有變量訪問的事情,下面寫個(gè)迭代器出來
def __len__(self):
"""返回向量長度(有多少個(gè)元素)"""
return len(self._values)
def __repr__(self):
return "Vector({})".format(self._values)
def __str__(self):
return "({})".format(", ".join(e for e in self._values))
def __getitem__(self, index):
"""取向量的第index個(gè)元素"""
return self._values[index]
def __add__(self, another):
"""向量加法,返回結(jié)果向量"""
assert len(self) == len(another), \
"Error in adding. Length of vectors must be same."
# 判斷維度的大小
# return Vector([a + b for a, b in zip(self._values, another._values)])
return Vector([a + b for a, b in zip(self, another)])
def __sub__(self, another):
"""向量減法,返回結(jié)果向量"""
assert len(self) == len(another), \
"Error in adding. Length of vectors must be same."
# 判斷維度的大小
# return Vector([a - b for a, b in zip(self._values, another._values)])
return Vector([a - b for a, b in zip(self, another)])
def __mul__(self, k):
"""返回?cái)?shù)量乘法的結(jié)果向量:slef * k"""
# 向量乘數(shù)
return Vector([k * e for e in self])
def __rmul__(self, k):
"""返回?cái)?shù)量乘法的結(jié)果向量:k * slef """
# 向量乘數(shù)
return self * k
def __iter__(self):
"""返回向量的迭代器"""
return self._values.__iter__()
def __pos__(self):
"""返回i向量取正的結(jié)果"""
return 1 * self
def __neg__(self):
""" 返回一個(gè)負(fù)值"""
return -1 * self
# 因?yàn)槭怯辛说?,所以這里可以直接使用for循環(huán)了
╰( ̄ω ̄o)
內(nèi)容還有很多,大家請(qǐng)持續(xù)關(guān)注~
聯(lián)系客服