Многие из присутствующих знают волшебный трюк: ХЗ почему, но вот такая программа с довольно приличной точностью вычисляет обратную величину квадратного корня из x.
float FastInvSqrt(float x) {
float xhalf = 0.5f * x;
int i = *(int*)&x; // представим биты float в виде целого числа
i = 0x5f3759df - (i >> 1); // какого черта здесь происходит ?
x = *(float*)&i;
x = x*(1.5f-(xhalf*x*x));
return x;
}
Чуть поменьше, но тоже немало народу знают, что если страшную константу 0x5f3759df заменить на не менее страшную 0x1fbd1df5, то та же самая функция, каким-то волшебным образом начнёт вычислять просто корень из x (не обратную величину).
Если кому-то, когда-то, хотелось понять, что же чёрт побери здесь происходит, то теперь у вас появилась такая возможность. Вот, читайте - полное разоблачение волшебных констант.
float FastInvSqrt(float x) {
float xhalf = 0.5f * x;
int i = *(int*)&x; // представим биты float в виде целого числа
i = 0x5f3759df - (i >> 1); // какого черта здесь происходит ?
x = *(float*)&i;
x = x*(1.5f-(xhalf*x*x));
return x;
}
void setup() {
Serial.begin(9600);
for (uint8_t i = 1; i < 25; i++) {
Serial.println(FastInvSqrt(i));
}
}
void loop() { }
и получил вот такое:
Спойлер
C:\Users\u\AppData\Local\Temp\arduino_modified_sketch_223041\sketch_jun02a.ino: In function 'float FastInvSqrt(float)':
C:\Users\u\AppData\Local\Temp\arduino_modified_sketch_223041\sketch_jun02a.ino:3:19: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
int i = *(int*)&x; // представим биты float в виде целого числа
C:\Users\u\AppData\Local\Temp\arduino_modified_sketch_223041\sketch_jun02a.ino:5:17: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
x = *(float*)&i;
C:\Users\u\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.6\cores\arduino\new.cpp: In function 'void* operator new(std::size_t, std::nothrow_t)':
C:\Users\u\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.6\cores\arduino\new.cpp:59:60: warning: unused parameter 'tag' [-Wunused-parameter]
void * operator new(std::size_t size, const std::nothrow_t tag) noexcept {
C:\Users\u\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.6\cores\arduino\new.cpp: In function 'void* operator new [](std::size_t, const std::nothrow_t&)':
C:\Users\u\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.6\cores\arduino\new.cpp:68:63: warning: unused parameter 'tag' [-Wunused-parameter]
void * operator new[](std::size_t size, const std::nothrow_t& tag) noexcept {
C:\Users\u\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.6\cores\arduino\new.cpp: In function 'void operator delete(void*, const std::nothrow_t&)':
C:\Users\u\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.6\cores\arduino\new.cpp:103:55: warning: unused parameter 'tag' [-Wunused-parameter]
void operator delete(void* ptr, const std::nothrow_t& tag) noexcept {
C:\Users\u\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.6\cores\arduino\new.cpp: In function 'void operator delete [](void*, const std::nothrow_t&)':
C:\Users\u\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.6\cores\arduino\new.cpp:106:57: warning: unused parameter 'tag' [-Wunused-parameter]
void operator delete[](void* ptr, const std::nothrow_t& tag) noexcept {