2009-11-17 11 views
5

Y at-il des inconvénients à ce code, qui semble être une version plus rapide (et correcte) de java.lang.Math.round?Implémentation plus rapide de Math.round?

public static long round(double d) { 

    if (d > 0) { 
     return (long) (d + 0.5d); 
    } else { 
     return (long) (d - 0.5d); 
    } 
} 

Il profite du fait que, en Java, tronquer à long arrondi à zéro.

+2

@TrueWill: Si c'est proprement dans une fonction correctement nommée ... Cela aurait-il vraiment de l'importance? Peut-être que c'est utilisé dans un programme mathématique. – Sivvy

+0

Il serait rare que vous trouviez une façon beaucoup plus rapide de faire quelque chose pour une méthode qui existe depuis 1.0 tout en maintenant une cohérence de 100% avec la méthode originale. – TofuBeer

+0

Absolument est une micro-optimisation, et dans un sens local en valait la peine. - mais ceux-ci ne sont pas recommandés pour un usage général. – mrjbq7

Répondre

15

Il existe quelques special cases que gère la méthode intégrée, que votre code ne gère pas. De la documentation:

  • Si l'argument est NaN, le résultat est 0.
  • Si l'argument est infini négatif ou d'une valeur inférieure ou égale à la valeur de Integer.MIN_VALUE, le résultat est égal à la valeur de Integer.MIN_VALUE.
  • Si l'argument est positif infini ou une valeur supérieure ou égale à égale à la valeur Integer.MAX_VALUE, le résultat est égal à la valeur Integer.MAX_VALUE.
5

Oui; vous ne tenez pas compte du débordement ou du débordement. D'un point de vue pragmatique, cela n'a pas d'importance pour votre application.

3

Je l'ai testé, et il existe un inconvénient potentiel clé qui n'a pas encore été décrit ici: Vous modifiez la méthode .

Math.round() implémente la règle "arrondir à moitié", alors que votre méthode round() implémente la règle "arrondir à moitié à partir de zéro".

Par exemple:

  • Math.round(-0.5d) =>0L
  • Your.round(-0.5d) =>-1L

Cela peut ou peut ne pas être un problème pour vous, mais vous devez comprendre que la méthode ci-dessus est pas un remplacement de Math.round(), même après les considérations NaN et infini déjà décrites.

Une autre question pertinente: Rounding negative numbers in Java

En ce qui concerne la performance, il n'y a pas de doute que la méthode ci-dessus est nettement plus rapide que Math.round() - il fonctionne dans environ 35% du temps pour générés de façon aléatoire des valeurs positives et négatives. Cela peut être une optimisation intéressante lorsque vous appelez cette méthode dans une boucle serrée. C'est encore mieux (25% du temps d'exécution) quand on donne seulement des valeurs positives, peut-être à cause du CPU utilisant branch prediction.

Math.round() est finalement implémenté par un appel JNI natif, ce qui pourrait être la cause de la différence de performance. This Sun/Oracle bug suggère qu'il pourrait y avoir une version Java pure dans j6u22, mais je ne peux pas voir où, et en effet Math.round() dans j6u23 se comporte de manière similaire à j6u16 dans mes tests. Je n'ai pas testé sur d'autres versions.