Question

Je pense notamment à la manière d'afficher les contrôles de pagination, lorsqu'on utilise un langage tel que C# ou Java.

Si j'ai X éléments que je souhaite afficher en morceaux de oui par page, combien de pages seront nécessaires ?

Était-ce utile?

La solution

J'ai trouvé une solution élégante :

int pageCount = (records + recordsPerPage - 1) / recordsPerPage;

Source: Conversion de nombres, Roland Backhouse, 2001

Autres conseils

La conversion en virgule flottante et inversement semble être une énorme perte de temps au niveau du processeur.

La solution d'Ian Nelson :

int pageCount = (records + recordsPerPage - 1) / recordsPerPage;

Peut être simplifié en :

int pageCount = (records - 1) / recordsPerPage + 1;

AFAICS, cela n'a pas le bug de débordement signalé par Brandon DuRette, et comme il ne l'utilise qu'une seule fois, vous n'avez pas besoin de stocker le recordsPerPage spécialement s'il provient d'une fonction coûteuse pour récupérer la valeur d'un fichier de configuration ou quelque chose.

C'est à dire.cela pourrait être inefficace si config.fetch_value utilisait une recherche dans la base de données ou quelque chose du genre :

int pageCount = (records + config.fetch_value('records per page') - 1) / config.fetch_value('records per page');

Cela crée une variable dont vous n'avez pas vraiment besoin, qui a probablement des implications (mineures) en matière de mémoire et qui demande tout simplement trop de saisie :

int recordsPerPage = config.fetch_value('records per page')
int pageCount = (records + recordsPerPage - 1) / recordsPerPage;

Tout cela ne représente qu'une seule ligne et ne récupère les données qu'une seule fois :

int pageCount = (records - 1) / config.fetch_value('records per page') + 1;

Pour C#, la solution consiste à convertir les valeurs en double (comme Math.Ceiling prend un double) :

int nPages = (int)Math.Ceiling((double)nItems / (double)nItemsPerPage);

En Java, vous devriez faire la même chose avec Math.ceil().

Cela devrait vous donner ce que vous voulez.Vous voudrez certainement x éléments divisés par y éléments par page, le problème est lorsque des nombres impairs apparaissent, donc s'il y a une page partielle, nous voulons également ajouter une page.

int x = number_of_items;
int y = items_per_page;

// with out library
int pages = x/y + (x % y > 0 ? 1 : 0)

// with library
int pages = (int)Math.Ceiling((double)x / (double)y);

La solution mathématique entière fournie par Ian est intéressante, mais souffre d'un bug de dépassement d'entier.En supposant que les variables sont toutes int, la solution pourrait être réécrite pour utiliser long maths et évitez le bug :

int pageCount = (-1L + records + recordsPerPage) / recordsPerPage;

Si records est un long, le bug demeure.La solution du module n'a pas le bug.

Une variante de La réponse de Nick Berardi cela évite un branchement:

int q = records / recordsPerPage, r = records % recordsPerPage;
int pageCount = q - (-r >> (Integer.SIZE - 1));

Note: (-r >> (Integer.SIZE - 1)) se compose du bit de signe de r, répété 32 fois (grâce à la signature de l'extension du >> opérateur.) Ceci est évalué à 0 si r est nul ou négatif, -1 si r est positif.Donc en le soustrayant de q a pour effet d'ajouter 1 si records % recordsPerPage > 0.

Pour les enregistrements == 0, la solution de rjmunro donne 1.La bonne solution est 0.Cela dit, si vous savez que records > 0 (et je suis sûr que nous avons tous supposé recordsPerPage > 0), alors la solution rjmunro donne des résultats corrects et ne présente aucun des problèmes de débordement.

int pageCount = 0;
if (records > 0)
{
    pageCount = (((records - 1) / recordsPerPage) + 1);
}
// no else required

Tous les solutions mathématiques entières seront plus efficaces que n'importe lequel des solutions à virgule flottante.

Besoin d'une méthode d'extension :

    public static int DivideUp(this int dividend, int divisor)
    {
        return (dividend + (divisor - 1)) / divisor;
    }

Pas de contrôle ici (débordement, DivideByZero, etc), n'hésitez pas à en ajouter si vous le souhaitez.À propos, pour ceux qui s'inquiètent de la surcharge d'invocation de méthode, des fonctions simples comme celle-ci pourraient de toute façon être intégrées par le compilateur, donc je ne pense pas que ce soit là où il faut s'inquiéter.Acclamations.

P.S.vous trouverez peut-être utile d'en être également conscient (il obtient le reste) :

    int remainder; 
    int result = Math.DivRem(dividend, divisor, out remainder);

Une autre alternative consiste à utiliser la fonction mod() (ou '%').S'il y a un reste non nul, incrémentez le résultat entier de la division.

Je fais ce qui suit, gère les éventuels débordements :

var totalPages = totalResults.IsDivisble(recordsperpage) ? totalResults/(recordsperpage) : totalResults/(recordsperpage) + 1;

Et utilisez cette extension s'il y a 0 résultat :

public static bool IsDivisble(this int x, int n)
{
           return (x%n) == 0;
}

Aussi, pour le numéro de page actuel (cela n'a pas été demandé mais cela pourrait être utile) :

var currentPage = (int) Math.Ceiling(recordsperpage/(double) recordsperpage) + 1;

Alternative pour supprimer les branchements lors des tests pour zéro :

int pageCount = (records + recordsPerPage - 1) / recordsPerPage * (records != 0);

Je ne sais pas si cela fonctionnera en C#, cela devrait le faire en C/C++.

pour C#, utilisez la fonction Math.Ceiling :

var pageCount= Math.Ceiling((double)myList.Count() / recordsPerPage);

et Java utilise la fonction Math.Ceil :

int n = (int) Math.ceil((double)myList.size() / recordsPerPage));

Une méthode générique, dont vous pouvez parcourir le résultat, peut être intéressante :

public static Object[][] chunk(Object[] src, int chunkSize) {

    int overflow = src.length%chunkSize;
    int numChunks = (src.length/chunkSize) + (overflow>0?1:0);
    Object[][] dest = new Object[numChunks][];      
    for (int i=0; i<numChunks; i++) {
        dest[i] = new Object[ (i<numChunks-1 || overflow==0) ? chunkSize : overflow ];
        System.arraycopy(src, i*chunkSize, dest[i], 0, dest[i].length); 
    }
    return dest;
}

J'avais un besoin similaire : je devais convertir les minutes en heures et en minutes.Ce que j'ai utilisé c'est :

int hrs = 0; int mins = 0;

float tm = totalmins;

if ( tm > 60 ) ( hrs = (int) (tm / 60);

mins = (int) (tm - (hrs * 60));

System.out.println("Total time in Hours & Minutes = " + hrs + ":" + mins);

Les solutions suivantes devraient mieux arrondir que les solutions ci-dessus, mais au détriment des performances (en raison du calcul en virgule flottante de 0,5*rctDenominator) :

uint64_t integerDivide( const uint64_t& rctNumerator, const uint64_t& rctDenominator )
{
  // Ensure .5 upwards is rounded up (otherwise integer division just truncates - ie gives no remainder)
  return (rctDenominator == 0) ? 0 : (rctNumerator + (int)(0.5*rctDenominator)) / rctDenominator;
}

Vous souhaiterez effectuer une division en virgule flottante, puis utiliser la fonction plafond pour arrondir la valeur à l'entier suivant.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top