魔鬼数字_
目錄
1,開方的近似計算 0x1fbd1df5
2,開方原理
3,開方倒數(shù)的近似計算
4,開方倒數(shù)原理
5,除法換成乘法?3435973837
進公司之前對于魔鬼數(shù)字的理解,是真魔鬼。
進公司之后發(fā)現(xiàn),2也是魔鬼數(shù)字。
收錄一下真魔鬼的魔鬼數(shù)字。
1,開方的近似計算 0x1fbd1df5
float MagicSqrt(float x) {float xhalf = x / 2;int i = *(int*)&x;i = 0x1fbd1df5 + (i >> 1);return *(float*)&i; }int main() {cout << MagicSqrt(2);return 0; }輸出1.47748
如果再加牛頓法進行精度優(yōu)化:
float MagicSqrt(float x) {float xhalf = x / 2;int i = *(int*)&x;i = 0x1fbd1df5 + (i >> 1);x = *(float*)&i;x = x / 2 + xhalf / x;x = x / 2 + xhalf / x;return x; }int main() {cout << MagicSqrt(2);return 0; }輸出1.41421
輸入5000輸出70.7107,誤差不到0.0001
2,開方原理
根據(jù)浮點數(shù)的編碼方案,可以表示成:
? ,其中s和e表示小數(shù)(0到1)和指數(shù)(-127到128)
當(dāng)0<x<1時,,其中c是一個常數(shù)。
所以上式簡化成
即
如果把浮點數(shù)的32位比特按照int來解讀,那么絕對值就等于
所以上式化成?
用不同方法估算的c值都在0.05左右,https://www.lomont.org/papers/2003/InvSqrt.pdf
給出了0.0450465是怎么算出來的。
所以
3,開方倒數(shù)的近似計算
float rsqrt(float number) {float y = number;long i = *(long *)&y;i = 0x5f3759df - (i >> 1);y = *(float *)&i;return y; }int main() {cout << rsqrt(2);return 0; }輸出0.716215
4,開方倒數(shù)原理
和開方原理類似,最后也是用到
其中c取0.0450465
5,除法換成乘法?3435973837
求一個5的倍數(shù)除5等于多少,可以換成乘法
int main() {cout << 100*3435973837;return 0; }輸出20
原理很簡單:
cout << 3435973837 * 5;? 會輸出1,發(fā)生了溢出截斷。
那么這個數(shù)是怎么來的呢?也很簡單,解不定方程
最小解是
除了5之外,其他所有奇數(shù)幾乎都可以這么搞。
總結(jié)
- 上一篇: java 把数据写入txt_java把集
- 下一篇: Ubuntu9.04安装小记,无图有真相