## 問題
你想[快速](http://en.wikipedia.org/wiki/Fast_inverse_square_root "http://en.wikipedia.org/wiki/Fast_inverse_square_root")的計算一個數字的逆平方根。
## 方法
根據 Quake III Arena?[源代碼](ftp://ftp.idsoftware.com/idstuff/source/quake3-1.32b-source.zip "ftp://ftp.idsoftware.com/idstuff/source/quake3-1.32b-source.zip"), 這種奇怪的算法使用整數運算,以及一個‘神奇的數字(幻數)’來計算逆平方根的近似值。 在此CoffeeScript的變種中,我不僅提供原始的經典之作,還有由[Chris Lomont](http://www.lomont.org/Math/Papers/2003/InvSqrt.pdf "http://www.lomont.org/Math/Papers/2003/InvSqrt.pdf")發現的新最佳的32位幻數,此外還有64位大小的幻數。
包含的另一個特征是能夠改變的精度水平。 這是通過控制執行[牛頓法](http://en.wikipedia.org/wiki/Newton%27s_method "http://en.wikipedia.org/wiki/Newton%27s_method")的迭代次數實現。
這個算法在經典的解法上仍然可以提升性能,這取決于計算機和精確水平。
用coffee編譯運行這段腳本: coffee -c script.coffee
然后復制粘貼編譯后的js代碼到你的瀏覽器JavaScript控制臺中。
提示:你需要一個瀏覽器支持?[類型化數組](https://developer.mozilla.org/en/JavaScript_typed_arrays "https://developer.mozilla.org/en/JavaScript_typed_arrays")。
參考:
1. [ftp://ftp.idsoftware.com/idstuff/source/quake3-1.32b-source.zip](ftp://ftp.idsoftware.com/idstuff/source/quake3-1.32b-source.zip)
2. [http://www.lomont.org/Math/Papers/2003/InvSqrt.pdf](http://www.lomont.org/Math/Papers/2003/InvSqrt.pdf)
3. [http://en.wikipedia.org/wiki/Newton%27s_method](http://en.wikipedia.org/wiki/Newton%27s_method)
4. [https://developer.mozilla.org/en/JavaScript_typed_arrays](https://developer.mozilla.org/en/JavaScript_typed_arrays)
5. [http://en.wikipedia.org/wiki/Fast_inverse_square_root](http://en.wikipedia.org/wiki/Fast_inverse_square_root)
源代碼來源于gist:?[https://gist.github.com/1036533](https://gist.github.com/1036533)
~~~
###
Author: Jason Giedymin <jasong _a_t_ apache -dot- org>
http://www.jasongiedymin.com
https://github.com/JasonGiedymin
Appearing in the Quake III Arena source code[1], this strange algorithm uses
integer operations along with a 'magic number' to calculate floating point
approximation values of inverse square roots[5].
In this CoffeeScript variant I supply the original classic, and newer optimal
32 bit magic numbers found by Chris Lomont[2]. Also supplied is the 64-bit
sized magic number.
Another feature included is the ability to alter the level of precision.
This is done by controling the number of iterations for performing Newton's
method[3].
Depending on the machine and level of percision this algorithm may still
provide performance increases over the classic.
To run this, compile the script with coffee:
coffee -c <this script>.coffee
Then copy & paste the compiled js code in to the JavaSript console of your
browser.
Note: You will need a browser which supports typed-arrays[4].
References:
[1] ftp://ftp.idsoftware.com/idstuff/source/quake3-1.32b-source.zip
[2] http://www.lomont.org/Math/Papers/2003/InvSqrt.pdf
[3] http://en.wikipedia.org/wiki/Newton%27s_method
[4] https://developer.mozilla.org/en/JavaScript_typed_arrays
[5] http://en.wikipedia.org/wiki/Fast_inverse_square_root
###
approx_const_quake_32 = 0x5f3759df # See [1]
approx_const_32 = 0x5f375a86 # See [2]
approx_const_64 = 0x5fe6eb50c7aa19f9 # See [2]
fastInvSqrt_typed = (n, precision=1) ->
# Using typed arrays. Right now only works in browsers.
# Node.JS version coming soon.
y = new Float32Array(1)
i = new Int32Array(y.buffer)
y[0] = n
i[0] = 0x5f375a86 - (i[0] >> 1)
for iter in [1...precision]
y[0] = y[0] * (1.5 - ((n * 0.5) * y[0] * y[0]))
return y[0]
### Sample single runs ###
testSingle = () ->
example_n = 10
console.log("Fast InvSqrt of 10, precision 1: #{fastInvSqrt_typed(example_n)}")
console.log("Fast InvSqrt of 10, precision 5: #{fastInvSqrt_typed(example_n, 5)}")
console.log("Fast InvSqrt of 10, precision 10: #{fastInvSqrt_typed(example_n, 10)}")
console.log("Fast InvSqrt of 10, precision 20: #{fastInvSqrt_typed(example_n, 20)}")
console.log("Classic of 10: #{1.0 / Math.sqrt(example_n)}")
testSingle()
~~~
## 討論
有問題嗎?
- 貢獻
- 作者
- 授權協議
- 1、Syntax
- 在服務端和客戶端重用代碼
- For循環
- 嵌入JavaScript代碼
- 值域
- 2、Classes and Objects
- 類方法和實例方法
- CoffeeScript式的Type函數
- 鏈式調用
- 克隆對象(深度克隆)
- 不存在就賦值為對象字面量
- 類變量
- 3、Strings
- 分割字符串
- 字符串匹配
- 查找子字符串
- 讓整個字符串小寫
- 大寫整個字符
- 去掉字符串首尾的空白
- 生成唯一的ID
- 首字母大寫
- 重復字符串
- 字符串插值
- 4、Arrays
- Python式的Zip函數 Python-like Zip Function
- 數組去重 Removing Duplicate Elements from Arrays
- 基于數組構建字典對象 Creating a dictionary Object from an Array
- 數組轉成字符串 Creating a String from an Array
- 檢查每一個元素 Testing Every Element
- 數組最大值
- 過濾數組 Filtering Arrays
- 定義區間數組 Define Ranges Array
- 轉置數組 Reversing Arrays
- 化簡數組 Reducing Arrays
- 使用數組來做值交換 Using Arrays to Swap Variables
- 列表解析 List Comprehensions
- 檢查值的類型是否是數組
- 連接數組
- 攪亂數組中的元素 Shuffling Array Elements
- 數組映射 Mapping Arrays
- 5、Dates and Times
- Calculate Phase of the Moon for a Date
- 找出某月的最后一天是幾號 Finding the Last Day of the Month
- 獲取兩個日期相差的天數 Get Days Between Two Dates
- 計算復活節島日期 Calculate the Date of Easter Sunday
- 計算感恩節的日期(美國和加拿大) Calculate the Date of Thanksgiving (USA and Canada)
- 計算上一個(下一個)月份 Finding Last (or Next) Month
- 6、Math
- 快速逆平方根
- 一個隨機整數的函數
- 更快的斐波那契算法
- 生成可預測的隨機數
- 弧度與度轉換
- 生成隨機數
- 數學常數
- 7、Functions
- 反抖動函數 Debounce Functions
- 參數數組化 Splat Arguments
- 當函數調用的括號不可以省略時 When Function Parentheses Are Not Optional
- 遞歸函數 Recursive Functions
- 8、Metaprogramming
- 擴展內置對象 Extending Built-in Objects
- 檢測并創建缺失的函數 Detecting and Creating Missing Functions
- 9、jQuery
- 回調綁定
- 創建jQuery插件
- AJAX
- 10、Ajax
- 不依賴jQuery的Ajax請求 Ajax Request Without jQuery
- 11、Regular Expressions
- 替換子字符串 Replacing Substrings
- 使用定點 Using Heregexes
- 使用HTML字符實體替換HTML標簽 Replacing HTML Tags with HTML Named Entities
- 搜索子字符串 Searching for Substrings
- 12、Networking
- 簡單的服務器
- 雙向客戶端
- 最簡單的HTTP客戶端
- 最簡單的HTTP服務器
- 簡單的客戶端
- 雙向服務端 Bi-Directional Server
- 13、Design Patterns
- 命令模式
- 單例模式
- 策略模式 Strategy Pattern
- 建造者模式 Builder Pattern
- 備忘錄模式 Memento Pattern
- 解釋器模式 Interpreter Pattern
- 裝飾者模式
- 橋接模式
- 工廠方法模式
- 14、Databases
- MongoDB
- SQLite
- 15、Testing
- 使用Jasmine測試