Comment faire pour arrondir le résultat de la division entière?
Je pense en particulier comment afficher la pagination des contrôles, lors de l'utilisation d'un langage comme C# ou Java.
Si j'ai x articles que je veux afficher dans des morceaux de y par page, nombre de pages qui seront nécessaires?
- Ai-je raté quelque chose? y/x + 1 fonctionne très bien (à condition de savoir l'opérateur / toujours arrondi vers le bas).
- si y et x sont égaux, y/x + 1 est une trop haute.
- Pour quelqu'un viens de trouver cela, cette réponse à une double question évite la conversion en double, et évite le débordement de préoccupations, en plus de fournir une explication claire.
- plus généralement, si
x
est divisible pary
,y/x + 1
serait une trop haute. - Non, il n'est pas d'éviter le débordement des préoccupations. C'est exactement la même solution que Ian Nelson posté ici.
Vous devez vous connecter pour publier un commentaire.
Trouvé une solution élégante:
Source: Nombre De Conversion, Roland Backhouse, 2001
pageCount = -((-records) // recordsPerPage)
.(records - 1) / recordsPerPage + 1
underflows lorsque les enregistrements == 0.La conversion à virgule flottante et en arrière semble comme une énorme perte de temps au niveau CPU.
Ian Nelson solution:
Peut être simplifiée:
AFAICS, ce n'est pas le dépassement de bug que Brandon DuRette souligné, et parce qu'il utilise seulement une fois, vous n'avez pas besoin de stocker les recordsPerPage spécialement s'il s'agit d'une fonction coûteuse pour aller chercher de la valeur à partir d'un fichier de configuration ou quelque chose.
I. e. cela pourrait être inefficace, si config.fetch_value utilisé une base de données de recherche ou de quelque chose:
Cela crée une variable que vous n'avez pas vraiment besoin, ce qui a probablement (mineur) de la mémoire implications et est juste trop tapant:
Ce n'est qu'une ligne, et seulement extrait les données à la fois:
-1 / 1 + 1 = 0
. Alors que ce n'est pas un super événement commun, il est important de garder à l'esprit si vous êtes en permettant aux utilisateurs d'ajuster la taille de la page. Donc, soit ne permettent pas aux utilisateurs d'avoir une taille de page de 1, faire une vérification sur la taille de la page, ou les deux (probablement préférable d'éviter un comportement inattendu).records + recordsPerPage
a une limite de 2^32 ou 2^64. Avec cette solution, vous ne pouvez utiliser qu'un entier signé pourrecords
, sinon ça va déborder à0 - 1
, doncrecords
est à la limite supérieure de 2^31 ou 2^63.Pour C# la solution est de jeter les valeurs en double (comme les Maths.Plafond prend une double):
En java, vous devriez faire la même chose avec les Mathématiques.ceil().
int
parce queMath.Ceiling
renvoie unedouble
oudecimal
, selon les types d'entrée.Cela devrait vous donner ce que vous voulez. Vous voudrez certainement les éléments x divisé par y articles par page, le problème, c'est quand inégale des numéros de venir, donc si il y a une page partielle, nous voulons aussi ajouter une page.
L'entier des mathématiques solution que Ian fourni est agréable, mais qui souffre d'un dépassement d'entier bug. En supposant que les variables sont toutes
int
, la solution pourrait être réécrit pour utiliserlong
de mathématiques et d'éviter le bug:int pageCount = (-1L + records + recordsPerPage) /recordsPerPage;
Si
records
est unlong
, le bug reste. Le module de la solution de ne pas avoir le bug.Une variante de Nick Berardi réponse qui évite une branche:
Remarque:
(-r >> (Integer.SIZE - 1))
consiste le bit de signe der
, répété 32 fois (grâce à l'extension du signe de la>>
opérateur). Elle correspond à la valeur 0 sir
est nul ou négatif, -1 sir
est positif. Afin de le soustraire deq
a pour effet d'ajouter 1 sirecords % recordsPerPage > 0
.Pour les enregistrements == 0, rjmunro de la solution 1. La bonne solution est de 0. Cela dit, si vous savez que des dossiers > 0 (et je suis sûr que nous avons tous supposé recordsPerPage > 0), puis rjmunro solution donne des résultats corrects et ne pas avoir les problèmes de débordement.
Tous l'entier des solutions mathématiques vont être plus efficace que tout de la virgule flottante solutions.
Dans le besoin d'une méthode d'extension:
Vérifie pas ici (dépassement de capacité,
DivideByZero
, etc), n'hésitez pas à ajouter si vous le souhaitez. Par ailleurs, pour ceux qui s'inquiètent de l'invocation de méthode de frais généraux, de simples fonctions, comme cela pourrait être incorporé par le compilateur de toute façon, donc je ne pense pas que c'est là où sont en cause. Des acclamations.P. S. vous trouverez peut-être utile d'être conscient de ce que bien (il obtient le reste):
DivideUp(4, -2)
renvoie 0 (doit être -2). Il n'est exacte que pour les entiers non négatifs qui n'est pas clair à partir de la réponse ou de la fonction de l'interface.Une autre alternative est d'utiliser le mod() fonction (ou"%"). Si il y a un non-zéro reste puis ajouter l'entier résultat de la division.
Je ne les suivants, gère toutes les débordements:
Et utiliser cette extension pour si il y a 0 résultats:
Aussi, pour le numéro de la page actuelle (n'était pas demandé, mais pourrait être utile):
Alternative à la suppression de ramification dans les tests pour le zéro:
Ne sais pas si cela va fonctionner en C#, devrait le faire en C/C++.
Une méthode générique, dont le résultat vous pouvez parcourir peuvent être d'intérêt:
Lists.partition(List, int)
) et ironiquement, lesize()
méthode de laList
(comme der09
) souffre de la bogue de dépassement mentionné dans Brandon DuRette réponse.J'avais un besoin similaire où j'avais besoin de convertir des Minutes en heures, & minutes. Ce que j'ai utilisé était:
Les éléments suivants doivent faire l'arrondissement de mieux que les solutions ci-dessus, mais au détriment des performances (en raison de virgule flottante de calcul de 0,5*rctDenominator):
Vous aurez envie de faire une division à virgule flottante, et ensuite utiliser la fonction ceiling, pour arrondir la valeur de l'entier suivant.