La racine carrée inverse rapide de Quake III semble utiliser une astuce en virgule flottante. Si je comprends bien, la représentation en virgule flottante peut avoir différentes implémentations.
Est-il donc possible d'implémenter la racine carrée inverse rapide en Javascript?
Renverrait-il le même résultat?
float Q_rsqrt(float number) {
long i;
float x2, y;
const float threehalfs = 1.5F;
x2 = number * 0.5F;
y = number;
i = * ( long * ) &y;
i = 0x5f3759df - ( i >> 1 );
y = * ( float * ) &i;
y = y * ( threehalfs - ( x2 * y * y ) );
return y;
}
javascript
Atav32
la source
la source
Réponses:
L'astuce dépend de la réinterprétation des bits d'un nombre à virgule flottante en tant qu'entiers et inversement, ce qui est possible en JavaScript en utilisant la fonction Tableaux typés , pour créer un tampon d'octets bruts avec plusieurs vues numériques.
Voici une conversion littérale du code que vous avez donné; notez que ce n'est pas exactement la même chose, car toutes les opérations arithmétiques en JavaScript sont en virgule flottante 64 bits, et non 32 bits, donc l'entrée sera nécessairement convertie. En outre, comme le code d'origine, cela dépend de la plate-forme en ce qu'il donnera des résultats non-sens si l'architecture du processeur utilise un ordre d'octets différent; si vous devez faire des choses comme ça, je recommande que votre application exécute d'abord un cas de test pour déterminer que les entiers et les flottants ont les représentations d'octets que vous attendez.
J'ai confirmé en observant un graphique que cela donne des résultats numériques raisonnables. Cependant, il n'est pas évident que cela améliorera les performances, car nous effectuons davantage d'opérations JavaScript de haut niveau. J'ai exécuté des tests de performance sur les navigateurs que j'ai à portée de main et j'ai constaté que cela
Q_rsqrt(number)
prenait 50% à 80% du temps pris par1/sqrt(number)
(Chrome, Firefox et Safari sur macOS, à partir d'avril 2018). Voici ma configuration de test complète:la source
In classic JavaScript, it is not possible to... reinterpreting the bits of a floating-point number as an integer
vraiment? C'était il y a des années, donc je ne me souviens pas exactement des opérations que j'utilisais, mais j'ai déjà écrit un analyseur de données en JavaScript qui convertirait une chaîne d'octets en une série d'entiers de N bits (N était défini dans l'en-tête). C'est assez similaire.