Diviser et Obtenir le Reste en même temps?
Apparemment, x86 (et probablement beaucoup d'autres jeux d'instructions) de mettre à la fois le quotient et le reste d'une opération de division dans des registres distincts.
Maintenant, nous pouvons probablement faire confiance à des compilateurs pour optimiser un code comme celui-ci par un seul appel à la fracture:
( x /6 )
( x % 6 )
Et ils n'ont probablement. Encore, n'importe quel langues (ou les bibliothèques, mais surtout à la recherche pour les langues) de soutien donnant à la fois la division et modulo résultats en même temps? Si oui, quelles sont-elles et Quelle est la syntaxe ressemble?
- Votre extrait de code n'est pas un exemple de quelque chose qui ne pourrait jamais être optimisé dans ce mode...
- Je viens de réaliser que j'avais la mauvaise extrait de code. Mis à jour il.
- Excellentes réponses de tout le monde. Suce que je ne peux en choisir un comme la "réponse" quand beaucoup d'entre eux sont des réponses valables.
Vous devez vous connecter pour publier un commentaire.
C a
div
etldiv
. Si ces générer des instructions pour le quotient et le reste dépendra de votre bibliothèque standard de mise en œuvre et le compilateur et les paramètres d'optimisation. En commençant par le C99, vous avez égalementlldiv
pour un plus grand nombre.div
en 4.8: stackoverflow.com/questions/4361979/...div(var, 10)
compile en un véritable appel de la fonction, et ladiv
mise en œuvre de bibliothèque n'a pas les informations que le diviseur est une constante10
. Donc il ne peut pas utiliser les un inverse multiplicatif. Même avec un temps d'exécution variable diviseur, vous obtenez la plus grande taille de code et non en ligne de l'appel de fonction sur x86.memcpy
), mais ils ne sont pas, de sorte qu'ils n'optimisent pas presque aussi bien qu'ils le pourraient. Ainsi, il est beaucoup mieux d'utilisern / d
etn % d
à proximité, avec exactement le mêmen
etd
, de sorte que le compilateur peut optimiser de manière fiable la division par une constante, la constante de propagation, et la portée de l'information. (par exemple, le compilateur connaît le résultat de la division par 10, c'est une plage plus petite que la pleineint
gamme, peut-être permettant d'optimiser par la suite.)libgcc.a
de la fonction, de sorte que vous n'avez probablement jamais même enregistrer le code de taille avec ces fonctions.div
et d'autres sans. Toujours test votre spécifiques de mise en œuvre avant de supposer que quelque chose est ou n'est pas optimisé.div
que de l'écriturer = x%y; q = x/y;
? C'est répandu, la plupart des bons compilateurs de l'optimiser à moins d'aliasing analyse s'arrête CST de travail (par exemple,x
ety
ne sont pas de simples variables locales). Si l'appel dediv
est la meilleure manière sur cette plate-forme, c'est ce que les compilateurs pouvait faire pour ouvrir codée%
et/
. Assurez-vous qu'il est bon de tester, mais je pense que l'open de codage est le plus sûr pari à travers plusieurs mises en œuvre.div()
appel de fonction optimisée pour obtenir les deux résultats à partir d'un seulDIV
instruction, où séparée/
et%
états fonctionnement efficace de l'ensemble du calcul deux fois (je ne me souviens pas le compilateur, c'était une plate-forme intégrée, quoique). Six
estvolatile
, vos résultats peuvent changer pour des raisons distinctes. De nouveau, toujours la mise à l'essai un comportement spécifique à votre cas d'utilisation spécifiques avant de les optimiser pour le/autour d'elle.Python n'.
Ce qui est étrange, parce que Python est un langage de haut niveau.
Ne sorte de Rubis:
* EDIT *
Il convient de noter que le but de ces opérateurs est sans doute de ne pas faire le travail aussi efficacement que possible, il est plus probable que les fonctions de l'exactitude de l'/des raisons de portabilité.
Pour ceux qui sont intéressés, je crois c'est le code du Python de mise en œuvre pour l'entier divmod:
divmod
s'exécute qu'une seule opération? Qu'est-ce que le code de cette fonction?divmod
simplement effectue les deux opérations séparément et les paquets les résultats, mais n'ont aucune preuve à offrir.En C#/.NET, vous avez
Math.DivRem
:http://msdn.microsoft.com/en-us/library/system.math.divrem.aspx
Mais selon ce fil ce n'est pas beaucoup d'une optimisation.
Common Lisp n': http://www.lispworks.com/documentation/HyperSpec/Body/f_floorc.htm
Comme Stringer Bell mentionné qu'il y avait
DivRem
qui n'est pas optimisé jusqu'à .NET 3.5.Sur .NET 4.0 il utilise NGen.
Les résultats que j'ai obtenu avec
Math.DivRem
(debug; version = ~11000ms)Résultats que j'ai obtenu avec
MyDivRem
(debug; version = ~11000ms)Projet ciblé pour x86.
Math.DivRem
Exemple d'utilisationSignatures de méthode
.NET 4.0 Code
.NET 4.0 IL
Référence MSDN
L' .NET framework a
Math.DivRem
:Bien que,
DivRem
est juste un wrapper autour de quelque chose comme ceci:(Je n'ai aucune idée de savoir si ou non la gigue peut/veut optimiser ce genre de chose en une seule instruction.)
FWIW, Haskell a deux
divMod
etquotRem
que ce qui correspond directement à l'instruction machine (selon Partie intégrante des opérateurs quot vs div), tandis quedivMod
peut pas.Cette déclaration est le résultat d'une de reste
En Java la classe
BigDecimal
a l'opérationdivideAndRemainder
renvoyer un tableau de 2 éléments du résultat et de reste de la division.Javadoc: https://docs.oracle.com/javase/7/docs/api/java/math/BigDecimal.html#divideAndRemainder(java.math.BigDecimal)