Rapidement carré un double


Je cherche le moyen le plus rapide de placer un double (double d). Jusqu'à présent, je suis venu avec deux approches:

1. d*d
2. Math.pow(d, 2)

Pour tester les performances, j'ai mis en place trois cas de test, dans chacun je génère des nombres aléatoires en utilisant la même graine pour les trois cas et calcule simplement le nombre au carré dans une boucle 100 000 000 fois.

Dans le premier cas de test, les nombres sont générés en utilisant random.nextDouble(), dans le second cas en utilisant random.nextDouble()*Double.MAX_VALUE et dans le troisième en utilisant random.nextDouble()*Double.MIN_VALUE.

Les résultats d'un couple de runs (résultats approximatifs, il y a toujours une certaine variation, exécuter en utilisant java 1.8, compilé pour java 1.6 sur Mac OSX Mavericks)

Approach | Case 1 | Case 2 | Case 3
---------•--------•--------•-------
    1    | ~2.16s | ~2.16s | ~2.16s
    2    | ~9s    | ~30s   | ~60s

La conclusion semble être que l'approche 1 est beaucoup plus rapide mais aussi que Math.pow semble se comporter un peu bizarre.

J'ai Donc deux questions:

1 Pourquoi est - Math.pow si lent, et pourquoi faut-il faire face mal avec > 1 et encore pire avec < -1 numéros?

2 Existe-t-il un moyen d'améliorer les performances par rapport à ce que je suggéré comme approche 1? Je pensais à quelque chose comme:

long l = Double.doubleToRawLongBits(d);
long sign = (l & (1 << 63));
Double.longBitsToDouble((l<<1)&sign);

Mais c'est a) faux, et b) à peu près la même vitesse que l'approche 1.

Author: Samuel, 2014-08-08

3 answers

Le moyen le plus rapide de quadrature un nombre est de le multiplier par lui-même.

Pourquoi Math.pow est-il si lent?

Ce n'est vraiment pas le cas, mais il effectue une exponentiation au lieu d'une simple multiplication.

Et pourquoi fait-il mal avec > 1 et pire encore avec

D'abord, parce qu'il fait le calcul. À partir du Javadoc , il contient également des tests pour de nombreux cas d'angle. Enfin, je ne voudrais pas trop compter sur votre micro-benchmark.

 8
Author: Elliott Frisch, 2014-08-08 14:33:53

La quadrature en se multipliant avec self est la plus rapide. Parce que cette approche peut être directement traduite en bytecode simple et non ramifié (et donc, indirectement, en code machine).

Mathématiques.pow () est une fonction assez complexe qui vient avec diverses garanties pour les cas de bord. Et il doit être appelé au lieu d'être en ligne.

 5
Author: Durandal, 2014-08-08 14:34:08

Math.pow() est lent car il doit traiter le cas générique ou élever un nombre à une puissance donnée.
Quant à savoir pourquoi il est plus lent avec des nombres négatifs, c'est parce qu'il doit tester si la puissance est positive ou négative afin de donner le signe, c'est donc une opération de plus à faire.

 2
Author: Varpie, 2014-08-08 14:50:17