[英]What is the exact value of the first type-punning in fast square root inverse algorithm?
有了這段代碼,(這是Quake 3中使用的眾所周知的快速平方根逆算法),我無法理解打印輸出。 我從表面上了解了整個算法,但希望獲得深入的了解。 printf
打印時i
的值是什么? 這給了我1120403456。 是否取決於計算機的體系結構? 我讀過某處這樣的類型操縱會導致不確定的行為。 在另一個網站上,我讀到了那時i
的值是此變量使用的位的確切值。 我對此感到困惑,並且誠實地期望i
的值為100。如何解釋結果1120403456? 如何將此值轉換為十進制100? 這些位是以某種方式編碼的嗎? 這是代碼摘錄:
#include<stdio.h>
int main()
{
float x = 100;
float xhalf = 0.5f*x;
int i = *(int*)&x;
printf("%d", i);
i = 0x5f3759df - (i>>1);
x = *(float*)&i;
x = x*(1.5f-xhalf*x*x);
return x;
}
在int i = *(int*)&x;
之后打印的i
的值int i = *(int*)&x;
是浮點數100.0
的位表示形式,這是x初始化的對象。 由於您在printf
使用%d
格式,因此它將表示形式打印為十進制整數。
的位模式100.0
在IEEE 32位float
是0x42c80000
,這是1120403456
十進制
要將1120403456或任何其他數字解釋為IEEE基本的32位二進制浮點數:
如果指數代碼為0,則表示2 -126 ,並且有效位數將以“ 0.”而不是“ 1”開頭。
如果指數代碼為255,且有效位為零,則對象將表示無窮大(根據符號位為+∞或-∞)。 如果指數代碼為255,並且有效位不為零,則該對象將表示非數字(NaN)。 NaN還有其他語義未包含在此答案中。
它比Quake III早得多 ,盡管確切的魔術常數有所變化。
根據IEEE-754(大多數現代計算機使用的)對有限單精度浮點數進行編碼是
31 30 23 22 0
├─┼─┬─┬─┬─┬─┬─┬─┬─┼─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┤
│S│ Exponent │ Mantissa │
└─┴───────────────┴─────────────────────────────────────────────┘
最高位S
是符號。 如果設置,則該值為負,否則為正。
如果Exponent
和Mantissa
均為零,則值為0.0(如果S
為零)或-0.0(如果S
為1)。
如果Exponent
為零,但Mantissa
非零,則您有一個非常接近零的非正規數 。
Exponent
為255(所有位均已設置)的表示形式保留為無窮大(如果Mantissa
為零),而不是數字(如果Mantissa
不為零)。
對於從1到254(含)之間的Exponent
值, Mantissa
包含Mantissa
的小數位,在整數位置含一個隱式1(這是(1)
在0 10000001 (1)1011011011011011011011
。)換句話說,對於這些Exponent
值, Mantissa
表示的值是從1.00000000000000000000000 2 (十進制1.0)到1.11111111111111111111111 2 (十進制1.99999994)(含)。
= Exponent
(between 1 and 254, inclusive), and the logical value of Mantissa
(between 1.0 and 1.99999994), then the value the single-precision floating point represents is 現在,如果我們僅考慮非負值( S
清除), = Exponent
(1到254之間,包括1和254之間),而為Mantissa
的邏輯值(1.0到1.99999994之間),則值為單精度浮點點代表是
= 2 - 127 × = 2 -127 ×
127是指數偏差。 is 平方根是
= 2 ( - 127)/2 × √ = 2 /2 - 127 × 2 63 × √2 × √ = - 127)/ = 2 / 2 - 127×2 63×√2×√
和平方根反比,這是這里的目標運算,
= 2 (127 - )/2 × 1/√ = 2 - /2 - 127 × 2 63 × √2 × 1/√ 1 = 2(127 - 2×1 = 2 - / 2 - 127×2 63×√2×1 /√
注意2127/2 = 2 63.5 = 2 63 ×√2。
. 如果我們采用整數表示形式,並將其向右移一位,我們實際上將減半。 要乘以2 63 ,我們需要將63加到指數上。 63×2 23 。 , we effectively just multiply by /2. 然而代替,對於平方根運算,乘以√2×√ ,我們有效地只是乘以 / 2。 這意味着(將整數表示右移一位,然后將63加到指數上)會得出平方根的估計值,對於大於1.0的自變量,其平方差在0.7071067到0.75之間,而系數在0.7071067到0.05之間。 0和1之間的值是1448.155(對於√0,它的輸出為5.421×10 -20,對於√1,它的輸出為0.75。)
. 注意,對於平方根的倒數運算,我們希望對求反。
). 事實證明,如果向右一位移位整數表示,然后減去從(1 01111100 1101110101100111011111)2(1597463007十進制,十六進制0x5f3759df,的√2127≈13043817825332782212單精度浮點近似值) ,你得到的平方根的倒數(1 的一個很好的近似。 對於所有有限的普通自變量,近似值與正確值之間的距離為0.965624至1.0339603。 一個非常好的近似值! 對於頂部的平方根逆運算,您需要做的是一兩次牛頓方法迭代。 ) = 0 iff = 1/√ you need f( ) = 1/ ^2 - . So, each iteration in is - f( )/f'( ) = × (1.5 - 0.5 × × × . Which should look quite familiar.) (對於 0當且僅當 = 1 您需要 1 / ^ 2 - 因此,在每次迭代是 - ×(1.5-0.5× × × 。應該看起來很熟悉。)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.