web-dev-qa-db-fra.com

comment arrondir toujours au prochain entier

j'essaie de trouver le nombre total de pages dans la création d'un pageur sur un site Web (donc je veux que le résultat soit un entier. Je reçois une liste d'enregistrements et je souhaite être divisé en 10 par page (le nombre de pages).

quand je fais ça:

list.Count() / 10

ou

list.Count() / (decimal)10

et la list.Count() =12, j'obtiens un résultat de 1.

Comment pourrais-je le coder pour que j'obtienne 2 Dans ce cas (le reste devrait toujours ajouter 1)

78
leora
Math.Ceiling((double)list.Count() / 10);
164
Rob

(list.Count() + 9) / 10

Tout le reste ici est excessif ou tout simplement faux (à l'exception de réponse de bestsss , ce qui est génial). Nous faisons pas vouloir le temps système d'un appel de fonction (Math.Truncate(), Math.Ceiling(), etc.) quand de simples calculs suffisent.


La question de OP généralise ( principe de casier ) en:

De combien de boîtes ai-je besoin pour stocker des objets x si seulement des objets y entrent dans chaque boîte?

La solution:

  1. dérive de la réalisation que la dernière case peut-être soit partiellement vide, et
  2. est (x + y - 1) ÷ y en utilisant division entière .

Vous vous souviendrez de 3rd note mathématique que division entière est ce que nous faisons lorsque nous disons 5 ÷ 2 = 2.

Division en virgule flottante est le moment où nous disons 5 ÷ 2 = 2.5, Mais nous ne pas Je veux ça ici.

De nombreux langages de programmation prennent en charge la division entière. Dans les langues dérivées de C, vous l'obtenez automatiquement lorsque vous divisez int types (short, int, long, etc.). La partie restante/fraction de toute opération de division est simplement supprimée, ainsi:

5 / 2 == 2

En remplaçant notre question initiale par x = 5 Et y = 2, Nous avons:

Combien de boîtes ai-je besoin de stocker 5 objets si seulement 2 objets entrent dans chaque boîte?

La réponse devrait maintenant être évidente: 3 boxes - les deux premières boîtes contiennent deux objets chacune et la dernière boîte en contient un.

(x + y - 1) ÷ y =
(5 + 2 - 1) ÷ 2 =
6 ÷ 2 =
3

Donc, pour la question initiale, x = list.Count(), y = 10, Qui donne la solution sans appels de fonction supplémentaires:

(list.Count() + 9) / 10

57
par

Un repère approprié ou comment le nombre peut mentir

Après l’argument à propos de Math.ceil(value/10d) et (value+9)/10 J'ai fini par coder un code de référence non mort, en mode non interprétable. Je disais qu'écrire un micro-test n'était pas une tâche facile. Le code ci-dessous illustre ceci:

00:21:40.109 starting up....
00:21:40.140 doubleCeil: 19444599
00:21:40.140 integerCeil: 19444599
00:21:40.140 warming up...
00:21:44.375 warmup doubleCeil: 194445990000
00:21:44.625 warmup integerCeil: 194445990000
00:22:27.437 exec doubleCeil: 1944459900000, elapsed: 42.806s
00:22:29.796 exec integerCeil: 1944459900000, elapsed: 2.363s

Le repère est dans Java car je sais bien comment Hotspot optimise et garantit un résultat juste. Avec de tels résultats, aucune statistique, aucun bruit ni rien ne peut le ternir.

Le nombre entier est incroyablement beaucoup plus rapide.

Le code

package t1;

import Java.math.BigDecimal;

import Java.util.Random;

public class Div {
    static int[] vals;

    static long doubleCeil(){
        int[] v= vals;
        long sum = 0;
        for (int i=0;i<v.length;i++){
            int value = v[i];
            sum+=Math.ceil(value/10d);
        }
        return sum;
    }

    static long integerCeil(){      
        int[] v= vals;
        long sum = 0;
        for (int i=0;i<v.length;i++){
            int value = v[i];
            sum+=(value+9)/10;
        }
        return sum;     
    }

    public static void main(String[] args) {
        vals = new  int[7000];
        Random r= new Random(77);
        for (int i = 0; i < vals.length; i++) {
            vals[i] = r.nextInt(55555);
        }
        log("starting up....");

        log("doubleCeil: %d", doubleCeil());
        log("integerCeil: %d", integerCeil());
        log("warming up...");       

        final int warmupCount = (int) 1e4;
        log("warmup doubleCeil: %d", execDoubleCeil(warmupCount));
        log("warmup integerCeil: %d", execIntegerCeil(warmupCount));

        final int execCount = (int) 1e5;

        {       
        long time = System.nanoTime();
        long s = execDoubleCeil(execCount);
        long elapsed = System.nanoTime() - time;
        log("exec doubleCeil: %d, elapsed: %.3fs",  s, BigDecimal.valueOf(elapsed, 9));
        }

        {
        long time = System.nanoTime();
        long s = execIntegerCeil(execCount);
        long elapsed = System.nanoTime() - time;
        log("exec integerCeil: %d, elapsed: %.3fs",  s, BigDecimal.valueOf(elapsed, 9));            
        }
    }

    static long execDoubleCeil(int count){
        long sum = 0;
        for(int i=0;i<count;i++){
            sum+=doubleCeil();
        }
        return sum;
    }


    static long execIntegerCeil(int count){
        long sum = 0;
        for(int i=0;i<count;i++){
            sum+=integerCeil();
        }
        return sum;
    }

    static void log(String msg, Object... params){
        String s = params.length>0?String.format(msg, params):msg;
        System.out.printf("%tH:%<tM:%<tS.%<tL %s%n", new Long(System.currentTimeMillis()), s);
    }   
}
20
bestsss

Cela fonctionnera également:

c = (count - 1) / 10 + 1;
17
finnw
3
mfanto

Je pense que le moyen le plus simple est de diviser deux nombres entiers et d’augmenter par un:

int r = list.Count() / 10;
r += (list.Count() % 10 == 0 ? 0 : 1);

Pas besoin de bibliothèques ou de fonctions.

édité avec le bon code.

3
Radoslav Georgiev

Vérifiez en utilisant mod - s'il y a un reste, incrémentez simplement la valeur de un.

0
Den Delimarsky