貢獻者: jouae, jserv
為什麼 A4 紙會被稱為 A4?這全歸功於數學原理。A4 紙正好是 A3 紙的一半、A2 紙的四分之一,而 A0 紙(面積為 1 平方公尺,但並非正方形)的十六分之一。這一系列尺寸均遵循長寬比
這套尺寸系統的一大優點就在於紙張可輕易對半切割,產生出尺寸一致且比例不變的小紙張。當初制定 A 系列規格時,正是要求無論紙張大小如何變化,其長邊與短邊的比例必須保持一致,以避免在尺寸轉換時出現邊界問題,而這個比例始終固定為
另一方面,B 系列紙張 (如 B5) 則不依循上述原則來設計,這也正是 A4 與 B5 在尺寸規格上的主要差異之一。
邊長為 1 的正方形對角線長度是多少?中學數學提到,直角邊長為 1 的等腰 直角 三角形的斜邊長就是
延伸閱讀: 第一次數學危機,天才是怎麼被扼殺的?
畢氏定理的畢氏,指古希臘學者畢達哥拉斯。相傳此定理在當時是由畢達哥拉斯所發現,雖然古巴比倫人在他出生前的一千多年前就已發現該道理,但至少可知道,畢達哥拉斯把這個定理又帶回來給西方世界,所以西方世界多用畢氏定理來稱這個常見的定理。
在數學之外,畢達哥拉斯也是集數學、天文、音樂理論於一身的高手,他願意將部分的知識傳播給大眾,而且他也是當時少數讓女性也能來聽講的學者 (當時禁止女性聽公開演講)。不過,這些知識也有分等級,分享給大眾聽的,是比較一般的知識,若你想提問,或者你想知道更高深的知識,你需要加入畢達哥拉斯學派。
畢達哥拉斯學派的正統信徒必須宣誓,不會將學派的秘密以及較高深的學說外流出去,同時也必須經過嚴格的訓練,才會被承認為正式的教徒。除此之外,還必須嚴守各種的清規戒律,某種程度就是在修行;同時也會將自己所研究出來的新成果,成就歸於導師畢達哥拉斯。
畢達哥拉斯等人對數學是有一定的狂熱,他們不是為了實際的應用而去鑽研數學。他們相信,透過數學,即可以探究這世界,上段所提的音樂理論,也是從數學推演出來的。為了抽象地去形容宇宙,或者單純只是為了美,畢達哥拉斯的學派在數學上也有很多的特殊想法,例如:萬物皆數。
萬物皆數,照字面上的意思就是萬物的本質皆是數字,這也是為什麼他們相信能利用數學來尋找真理。這個數是有嚴謹定義的,或者說,他們認為所有的數都有一個性質:可公度性。
要如何理解可公度性呢?若用線段長度來看,兩條線段之間必定能用一個特殊長度的整數倍來形容,例如 2 公分和 6 公分,可寫成
例如 7, 5.5
7, 5.5, 4, 2.5, 1.5, 1 0.5
,類似輾轉相除法找最大公因數的手法。
可公度性的另一種說法是:畢達哥拉斯認為所有的數,皆是整數或者二個非零整數的比值,也就是有理數。等等,這觀點和我們今日所知的數學原理不一致,發展的轉折就要提及希帕索斯 (Hippasus)。
希帕索斯是畢達哥拉斯學派的信徒,傳聞他非常認真,亦愛鑽研可公度性這個性質。有次他鑽研正五邊形的性質時,發現有兩條線段的長度,不論怎樣也無法找到可公度性所需要的特殊長度,只能無窮無盡的切割下去,沒有停止的那天。換言之,這代表這兩條線段並沒有可公度性這個性質,那麼,他們當初所相信的一個性質 —— 所有數都是可公度的,便是錯誤的,或者說,這世界上存在著不是整數、亦不能寫成兩整數比值的數。
後來希帕索斯改良使用更為直覺的方式,利用正方形的對角線與邊長,來說明存在兩數是不可公度的。
在畢達哥拉斯的指使或者漠視下,希帕索斯被門徒淹死在河裡。有人說畢達哥拉斯也搞政治,但其地位後來已岌岌可危,不容許再出現「學說錯誤」這樣的汙點。有的故事則說,希帕索斯提出不可公度這件事時,畢達哥拉斯已死去一段日子,被處死這件事情與畢達哥拉斯沒有太大關係。也有故事說,希帕索斯是與同門搭船時,與大家爭論不可公度這件事情時,被惱怒的同門丟下船溺死的。
無論是哪個版本,都指向諷刺的結果:希帕索斯運用理性找出的真相,被當時最能代表理性、邏輯和數學的一群人否定,而他的生命也被這群人不理性的抹殺。
仔細想想,畢達哥拉斯或者其學派的人,不可能不理解希帕索斯提出的疑慮,或者說不定,以畢達哥拉斯這樣的大師來說,他早就發現這件事情也不稀奇,但何以這些信徒仍選擇抹殺這個發現問題的學生呢?
因為信仰,不是宗教上的信仰,而是內心認同的價值觀。
畢達哥拉斯一生都在追求真理,同時他也不斷的宣揚萬物皆數這樣的想法。試著這麼想,如果有一天,你發現「真理」與你所想像的不同,跟你這一生所信奉的不一樣,也與你這大半輩子所宣揚的有所違背,你會做甚麼選擇?承認錯誤,讓自己變得更接近真理?
只可惜多數的人,可能也包含畢達哥拉斯與其信徒,沒有那麼大的勇氣去否定他們的信仰,去承認過去的努力只是個錯誤。因為這也是在否定他自己。如果他們是自己發現了這個事實,那麼能採取的,只能欺騙自己。
如果一件事情變成信仰,而信仰者卻沒有透過自省或質疑來去強化信念,那麼他的信仰即使看起來很堅定,也就只是虛有其表。在這種情況之下,你會發現他們為鞏固那並不是很堅固的信仰,會編撰出很多理由,即使這些理由從邏輯或知識上來看根本過於荒謬。
那麼,是否因他們邏輯推理能力不足、學識不夠豐富,才無法藉由理性與科學證據來修正自己的信仰呢?
不是,邏輯和知識當然是承認錯誤的必要條件,但即使他們有這些能力,若不曾自省與質疑,那麼這些能力也只會變成他們用來找尋藉口或荒謬理由的工具而已。看前面的故事就知道,即使當代最有邏輯與學識的一群人,一旦把教條當成不可質疑的信仰時,就算有人提出毫無瑕疵的證據質疑其說法,也只會像希帕索斯一樣,被這樣想要堅定自己搖搖欲墜的信仰之人推向深淵抹除,而在這種情形下,恐怕還有很多不同名字的希帕索斯這樣的消失在這個世界上。
我們藉由中學的數學,已知無理數的存在 (或者不可公度的存在),可大概推得,希帕索斯的發現並沒有隨著他的生命而消失。這個理論後來似乎隨著畢達哥拉斯學派的式微或者教條約束力的減弱,也漸漸流傳出去。這理論沒有沉到水裡,至於希帕索斯的發現是否對他的信仰 (數學) 造成了傷害呢?的確這個發現造成了第一次數學危機,但是也讓數學發展向前邁進了一大步。
別讓信仰殺死希帕索斯,因為他會帶領我們更走向真理。
以上改寫自 因信仰而死的希帕索斯
針對這個數學問題,考古學家發現在西元前 1800 年的古巴比倫泥板上已記載答案。
兩河流域文明時代最早的居民是蘇美人,在公元前 4000 年就抵達幼發拉底河和底格里斯河之間的美索不達米亞平原,大體位於現今的伊拉克。屬于塞姆語系的阿卡德人、巴比倫人、亞述人以及迦勒底人,繼承和發展蘇美人的成就,使兩河流域的文明成為人類文明史上重要的一頁。其中,巴比倫人的成就最大,因此兩河流域的文明又被稱為巴比倫文明。
兩河流域的居民主要用使用牛、驢拉著木犁耕地,古代兩河地區的金屬制造工藝達到了相當純熟的水平。古巴比倫人使用楔形文字表示數字,以六十進位進行計算。考古學家在中東地區發掘了數以萬計的古巴比倫泥板碎片,其中一片現存於耶魯大學的泥板依稀刻印著一個正方形的對角線的圖案,以及一排以楔形文字的數字。
後來考古學家解譯出上圖這組楔形數字是: 1
, 24
, 51
, 10
。
由於古巴比倫人用的是六十位系統,將這組數字轉換為十進位的數值得到以下:
這個數字極為近似
泥板上還給出了一個計算的例子,在正方形邊線上標註數字
這個值正是
至於東亞採用一日十二時辰的制度可能源於漢代曆法,採取十二支作為劃分是基於天文觀測的結果。後來為了更精確的計時,改用一刻六十分的制度,考量點如下:
整個時間計量系統的發展反映人類持續強化對自然界週期性運行規律的認識。從十時制到十二時制、從六十分制到公制,都是為了更適應天文觀測和農耕生活的需要。
古巴比倫人的時代距今已約 3800 年之久,我們無法確實知道古巴比倫人是如何計算出如此精準的
在估算
現在考慮三個數 1
, 2
, 4
,由於 1 < 2 < 4
,如果對這三個數開平方根也會有下面的關係:
這裡 1
和 4
都是平方數,可以很容易地算出
這個式子告訴我們 1
和 2
之間,不過我們還不能確定 1
抑或靠近 2
。
這個情況下我們可以用一個方法更進一步確定 1
到 2
再細分為 10 等分,也就是 1.1
, 1.2
, …, 1.9
, 2
,再計算每一個細分刻度的平方:
在數線上方我們列出 n 平方根的十等分值,在下方列出相對應的 n = (n平方根)2 的值。我們可以看到 n = (n平方根)2 有一個重要的變化點,也就是由 1.96
遞增到 2.25
之處,遞增的 n 值由小於 2
變成大於 2
:
而我們要找的
藉由這樣細分刻度的方法,我們可以將 1.4
和 1.5
之間。這個方法就稱為十分逼近法。
再一次利用十分逼近法,我們將 1.4
和 1.5
之間再細分為 10 等分:
這一次跨越 2
的區間落在 1.9881
和 2.0164
之間:
在這個關鍵的區間我們可以再次觀察到:
因此確定了 1.41
,而小於 1.42
。如此重複運用十分逼近法可以求得更精確的
根據平方根的定義,一個數 n 的平方根會滿足 n = (n平方根)2。如果只考慮 n 平方根是正整數的部分,n 的平方根 =
平方根的英文叫做 square root,在數學表示式裡常常會用縮寫 sqrt
表示平方根,sqrt(n)
。
Google 的網頁搜尋列支援計算機功能,我們可在 Google 搜尋列鍵入sqrt(2)
:
這時 Google 會顯示出一個計算機的畫面,告訴我們 2 的平方根等於1.41421356237
:
這個看似簡單的動作事實上包含了輸入輸出的步驟和一個內建的平方根演算法;我們一開始在計算機裡輸入 n 的值等於 2,計算機依據內建的平方根演算法幫我們算出 n 平方根 = 1.41421356237
,然後輸出在答案列。
Google 也提供函式繪圖的功能,我們試試 Google 搜尋列中鍵入y=sqrt(x)
:
我們會看到 Google 返回一張 sqrt(x)
的圖:
這張圖的意義在於將函數 y=sqrt(x)
的幾何圖形畫在二維的卡氏座標系裡。可見縱軸座標表示的就是 n 平方根,橫軸座標表示的是 n。
y=sqrt(x)
的圖表畫出了一條抛物線,每一個 x
的點都可以透過平方根函式求得一個對應的 y
值,因此每一個橫軸上的 x
座標,對應到縱軸的y座標,就可以畫出一個點。例如圖中的 x = 2.00000347
,平方根函式就會算出對應的 y = 1.41421479
,然後在座標系描出這個點。
當程式掃描橫軸上很多的 x
座標,就可以繪製出這條 y=sqrt(x)
的抛物線。
y = sqrt(x)
,或說
二分逼近法有 4 個基本步驟:
y = 1
的地方,再將第二個邊界值設在 y = 2
的地方。y = 1.5
,我們將中間點也標註在線段上。x
值在落在左右那一個區間內。由於 1.5
。用二分逼近法重複到第 8 次可以計算出 1.4140625
和 1.41796
之間,不難發現二分計算法收斂的速度不快。
遞迴是程式語言中的一個重要概念。用遞迴法解決問題首先需要找出問題的規律性,然後將問題分解為同類的子問題,重複求解直到確定滿足我們要的答案。
遞迴強大的地方在於允許使用者用有限的語句描述無限的物件。許多電腦程式語言支援遞迴法,允許一個函式呼叫它自己,來達到遞迴的目的。
在二分逼近法和十分逼近法的程式裡,我們都運用遞迴技巧。遞迴有三個重要的步驟:
如果 0.0000001
之內,
展示影片: 二分逼近法和十分逼近法求平方根
數學理論部分參考:
實作部分參考:
定義:如果一點
通常在數學中對函數、方程等等,我們會對其(1)解的存在性和(2)解的唯一性感興趣,例如線性方程組中從矩陣的零空間(null space)知道線性系統的解空間,解是否唯一(nullity is zero)或是多組解(nullity is nonzero, hence the solutions can be the linear combination of the basis in null space)。
所以對於一個單變數函數在一區間是否有固定點?若有,該固定點是否唯一?是我們關心的議題。
假設函數
存在性證明:
令函數
考慮一輔助函數
看到此處有幾個關鍵點:
這就是在中學學過勘根定理的充分條件,勘根定理又稱 Bolzano's theorem 為中間值定理的推廣。所以根據中間值定理,存在一點
承上述存在性,連續函數
則存在唯一固定點
唯一性證明:
令連續函數
證明唯一性的常用手法之一:假設其不唯一,使用反證法得證其唯一。
假設一次可微函數
從
結合上述存在性與唯一性便是固定點定理(fixed point theorem)。
令函數
藉由迭代法
得到的數列
固定點定理證明:
從存在性與唯一性得知,唯一固定點
在證明收斂的部分,我們會想看
根據均值定理,存在
從
將上述推論的過程再做一次會得
以此類推最終可得一不等式
根據
最後得證數列
出自《Numerical Analysis 10/e》第 60 頁
程式碼
考慮函數
數值解為何?
從固定點的定義,我們需要定義一個函數
則固定點迭代函數
在單精度浮點數 float
運算下, p_0
為初始值,固定設定
使用這個方式來跑固定點迭代如下:
p_0: 1.500000
1 iteration:
p_i: -0.875000
relative error: 2.240230
2 iteration:
p_i: 6.732422
relative error: 5.367192
3 iteration:
p_i: -469.720032
relative error: 471.085266
4 iteration:
p_i: 102754568.000000
relative error: 102754568.000000
5 iteration:
p_i: -1084934299940933513248768.000000
relative error: 1084934299940933513248768.000000
6 iteration:
p_i: -nan
relative error: nan
從上圖看橘線部分為
藍線部分為 ,其實整個迭代過程圖像化就如圖中箭頭指向的過程。
何以程式輸出 nan
呢?固定點迭代不該會收斂嗎?
固定點的存在根據上述推導
那來檢查下剛剛的
可以看出函數
所以這題無法使用固定點迭代求根了嗎?答案是可以的。但要改寫原函數。
從另一個角度來想,原函數是因為非 contraction mapping 而導致固定點不存在,所以找一個有相同根並滿足存在性的函數即可。
從原方程改寫
將二次項以外移至等號右側後開根號
由於要找的根在
稍微改寫下形式,得到函數
再來確認函數
得到
得知值域
但此函數不滿足固定點定理的唯一性
這種不滿足固定點唯一性,但固定點存在的函數,是不穩定 (unstable) 的。
同時還有兩個函數可以求解原函數之根:
其中一次微分為:
在數值方法的分析中關心兩件事情:
以下會介紹關於收斂速率的計算以及固定點誤差分析方式。
使用
relative errors:
iteration\function
g1 g2 g3 g4
1-iter: 1.640918e+00 5.733551e-02 1.232774e-02 5.935535e-03
2-iter: 3.931346e+00 2.732934e-02 1.572250e-03 2.348857e-05
3-iter: 3.450593e+02 1.448223e-02 1.999584e-04 8.731810e-08
4-iter: 7.526539e+07 7.281020e-03 2.549689e-05
5-iter: 7.946898e+23 3.761838e-03 3.230770e-06
6-iter: nan 1.916894e-03
7-iter: 9.837258e-04
8-iter: 5.030396e-04
9-iter: 2.575884e-04
10-iter: 1.319376e-04
11-iter: 6.749689e-05
12-iter: 3.457797e-05
13-iter: 1.763826e-05
將上述數據取 log (避免尺度問題)繪製成圖如下:
從圖形上看 g4
取 log 後的相對誤差下降的速度遠小於 g3
和 g2
,從數據上看 g2
的相對誤差每一次迭代約小 2 倍; g3
的相對誤差每一次迭代約小 7 倍; g4
的相對誤差每一次迭代約小 252 倍。
從上述來看,這個迭代法在收斂至固定點的過程中,其誤差是有規律的乘上一個係數,同時在不同的函數下,由誤差構成的線斜率也不盡相同。那要怎麼分析且計算收斂方面的數據呢?請參考下數學推論過程。
收斂速率(Order of Convergence)定義:
令數列
某些教材討論收斂性時,參雜 rate 和 order 等詞彙,但在漢語卻不精準地翻譯翻譯為「速率」。本文依據《Numerical Analysis 10/e》的定義與英文名詞為,使用Image Not Showing Possible ReasonsLearn More →
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
稱作為 order of convegence, 稱作為 asymptotic error constant。
假設二次微分連續函數
證明:
對固定點
其中
兩邊減去
當
藉由上述結果,我們可粗略計算在線性收斂時,誤差以
以上述的例子來看:
比較特別的是
從泰勒定理可以得知,假設函數
其中剩餘項
只要
故
從上述推導的過程中,得知
考慮
公式:
算術-幾何平均值不等式
練習 LeetCode 69. Sqrt(x),對於求開根號的近似值,可用上述牛頓法來求解。
int mySqrt(int n)
{
if (n == 0)
return 0;
if (n < 4)
return 1;
unsigned int ans = n / 2;
if (ans > 65535) // 65535 = 2^16 - 1
ans = 65535;
while (ans * ans > n || (ans + 1) * (ans + 1) <= n)
ans = (ans + n / ans) / 2;
return ans;
}
注意到以下:
ans
可初始為 if (ans > 65535) ans = 65535;
是避免 ans * ans
可能會溢位從而導致錯誤,因此需要對初始狀態做額外的調整為了討論的便利,我們將上述實作稱為 newton
。
在例題中使用平方和公式來理解,如何從乘法到單純加減與位移運算來開平方根。先觀察其規律
三元平方和
四元平方和
考慮一般化的平方和
觀察規律可以發現
其中
總結上述兩個觀察,可知:
數值系統在二進位表示下為:
假設
其中
舉例來說,設
故
令
Python's integer square root algorithm 是由 Mark Dickinson 提出的查表演算法,並在 Python 3.8 中採用。
isqrt 的特性:
The algorithm is unusual in that it is almost branch-free, requiring only a single final correction step, and in that the number of required iterations is easily predicted in advance. The algorithm is efficient both at small scales and asymptotically, and represents an attractive compromise between speed and simplicity.
Heron's method
令
前述提及截斷誤差為
上述並非對整數平方根逼近,故為了處理整數取值逼近,上述牛頓法的迭代過程以下取整數函數改寫成
再來 Mark Dickinson 照著以下思路至證明存在整數根號
Lemma 2.
任意正整數
Lemma 4.
講了初始
Lemma 5.
證明少了
參考〈How to calculate a square root without a calculator〉,其方法的證明可見〈Why the square root algorithm works〉,應用到二進位〈Methods of computing square roots〉也相似,我們則可利用該方法把平方根換成較快的逐位元位移的運算。
以下是
令
假設
考慮
整理上面第一種情況
因此
LeetCode 69. Sqrt(x) 可運用上述想法,搭配二分搜尋法來實作:
typedef union {
float value;
uint32_t v_int;
} ieee_float_shape_type;
/* Get a 32 bit int from a float. */
#define EXTRACT_WORDS(ix0, d) \
do { \
ieee_float_shape_type ew_u; \
ew_u.value = (d); \
(ix0) = ew_u.v_int; \
} while (0)
int mySqrt(int n)
{
int32_t sign = 0x80000000;
int32_t ix0, m, i;
float x = n;
EXTRACT_WORDS(ix0, x);
/* take care of zero */
if (ix0 <= 0) {
if ((ix0 & (~sign)) == 0)
return x; /* sqrt(+-0) = +-0 */
if (ix0 < 0)
return (x - x) / (x - x); /* sqrt(-ve) = sNaN */
}
/* normalize x */
m = (ix0 >> 23);
if (m == 0) { /* subnormal x */
for (i = 0; (ix0 & 0x00800000) == 0; i++)
ix0 <<= 1;
m -= i - 1;
}
m -= 127; /* unbias exponent */
ix0 = (ix0 & 0x007fffff) | 0x00800000;
if (m & 1) /* odd m, double x to make it even */
ix0 += ix0;
m >>= 1; /* m = [m/2] */
/* binary search 'm' */
unsigned int head = 1 << m; // 2^m
unsigned int tail = 1 << (m + 1); // 2^(m+1)
unsigned int mid = (head + tail) >> 1; // same as (2^m + 2^(m+1)) / 2
while (1) {
if (n > (mid + 1) * (mid + 1)) {
head = mid;
mid = (head + tail) >> 1;
} else if (n < mid * mid) {
tail = mid;
mid = (head + tail) >> 1;
} else
break;
}
return mid;
}
先求出整數 n
開根號後結果的
為了討論的便利,我們將上述實作稱為 ieee754 + binary search
。
巨集 EXTRACT_WORDS
能將 32 位元整數轉成 float
,可用 bitmask 對應各部分的位置,參考底下:
0x80000000
0x7f800000
0x007fffff
float 表示式:
延伸閱讀: 〈你所不知道的 C 語言: 浮點數運算〉
將 float x
表示為
我們來比較前述二個整數平方根的效率。
首先考慮 n 較小的情況下,即 0 到 1000 的範圍,可見 ieee754 + binary search
的執行時間低於 newton
。
考慮到在數值範圍較大時,二分搜尋可能會導致時間變長,觀察在 x = 1,000,000
到 x = 10,000,000
間的執行時間差異。在 n 達 1,000,000 時,ieee754 + binary search
的執行時間低於 newton
實作。
3D 繪圖經常要計算平方根倒數,原理是牛頓法,避開開根號和除法運算,節省很多計算時間。
float Q_rsqrt( float number )
{
long i;
float x2, y;
const float threehalfs = 1.5F;
x2 = number * 0.5F;
y = number;
i = * ( long * ) &y; // evil floating point bit level hacking
i = 0x5f3759df - ( i >> 1 ); // what the fuck?
y = * ( float * ) &i;
y = y * ( threehalfs - ( x2 * y * y ) ); // 1st iteration
// y = y * ( threehalfs - ( x2 * y * y ) ); // 2nd iteration, this can be removed
return y;
}
《雷神之鎚 III》(Quake III) 的求反平方根的原始程式碼直到 QuakeCon 2005 才正式釋出,但早在 2002 年,反平方根快速演算法的程式碼就出現在論壇中。最初人們猜測是 John D. Carmack 寫下這段程式碼,但後者否定這個觀點,並猜測可能是先前曾幫 id Software 最佳化雷神之鎚的資深程式設計師 Terje Mathisen 寫下這段程式碼,後者則表示在 1990 年代初,曾見過過類似的實作,確切來說這段程式碼亦非他所作。現在所知的最早由 Gary Tarolli 在 SGI Indigo 中實作,但他亦坦承他僅對常數 R 的取值做一定的改進,並非該手法的原創者。向發明 MATLAB 而聞名的 Cleve Moler 查證後,Rys Sommefeldt 則認為原始的演算法是 Ardent Computer 公司的 Greg Walsh 所發明,但他也不能確認。
其中可以看到 magic number 0x5f3759df
, Chris Lomont 在之後求出當時他認為是最小誤差之 magic number 0x5f37642f
,但是其精度反而更低,隨後 Lomont 找到的最佳數字為 0x5f375a86
。
IEEE754 - 32bits
Value | Predicted | Tested | 1 Iteration(% | 2 Iterations(%) |
---|---|---|---|---|
0x5f3759df | 3.43758 | 3.43756 | 0.175228 | 4.66E-04 |
0x5f37642f | 3.42128 | 3.42128 | 0.177585 | 4.78E-04 |
0x5f375a86 | 3.43655 | 3.43652 | 0.175124 | 4.65E-04 |
至於這個 magic number 如何得到的
y = a0 + a1*x + a2*(x^2) + a3*(x^3) + a4*(x^4) + ...
y = 1/sqrt(x)
y = a0 + a1*x + [...truncated...]
a0 = 0x5f375a86
a1 = -0.5
y = 0x5f375a86 - 0.5*x
i = 0x5f375a86 - (i >> 1);