220 votes

Comment faire des chiffres arrondis à 100%

Examiner les quatre pourcentages ci-dessous, sous la forme d' float numéros de:

    13.626332%
    47.989636%
     9.596008%
    28.788024%
   -----------
   100.000000%

J'ai besoin de représenter ces pourcentages que des nombres entiers. Si j'utilise simplement Math.round(), je me retrouve avec un total de 101%.

14 + 48 + 10 + 29 = 101

Si j'utilise parseInt(), je me retrouve avec un total de 97%.

13 + 47 + 9 + 28 = 97

Qu'est ce qu'un bon algorithme pour représenter n'importe quel nombre de pourcentages que des nombres entiers, tout en conservant un total de 100%?


Edit: Après avoir lu certains des commentaires et des réponses, il y a clairement beaucoup de façons d'aller sur la résolution de ce.

Dans mon esprit, pour rester fidèle à l'un des numéros, le "bon" résultat c'est celui qui minimise l'erreur globale, définie par la façon dont beaucoup d'erreur d'arrondi introduirait par rapport à la valeur réelle:

        value  rounded     error               decision
   ----------------------------------------------------
    13.626332       14      2.7%          round up (14)
    47.989636       48      0.0%          round up (48)
     9.596008       10      4.0%    don't round up  (9)
    28.788024       29      2.7%          round up (29)

En cas d'égalité (3.33, 3.33, 3.33) une décision arbitraire peut être fait (par exemple, 3, 4, 3).

173voto

Varun Vohra Points 2083

Il existe de nombreuses façons de le faire, à condition que vous ne vous souciez pas de la confiance sur l'origine des données décimales.

La première et peut-être le plus populaire de la méthode du Plus fort Reste la Méthode

Ce qui est fondamentalement:

  1. L'arrondissement tout en bas
  2. L'obtention de la différence dans la somme et 100
  3. La distribution de la différence en ajoutant 1 pour les éléments dans l'ordre décroissant de leurs parties décimales

Dans votre cas, ce serait comme ceci:

13.626332%
47.989636%
 9.596008%
28.788024%

Si vous prenez l'entier de pièces, vous obtenez

13
47
 9
28

ce qui ajoute jusqu'à 97, et que vous voulez ajouter plus de trois. Maintenant, vous regardez les parties décimales, qui sont

.626332%
.989636%
.596008%
.788024%

et de prendre le plus grand, jusqu'à ce que le total atteint 100. Donc, vous obtiendrez:

14
48
 9
29

Alternativement, vous pouvez simplement choisi de montrer une décimale au lieu de valeurs entières. Donc, les chiffres seront 48.3 et de 23,9 etc. Cela baisse la variance à partir de 100 par beaucoup.

49voto

paxdiablo Points 341644

Dépend de la façon dont 'précise' vous en avez besoin pour être. Une option est de simplement garder la somme des nombres arrondis et, au lieu de l'arrondissement de la dernière, il suffit de le mettre à l' 100 - that sum. Puis c'est la garantie d'ajouter jusqu'à 100.

Qui ignore le fait qu'il serait probablement plus judicieux de le faire à l' 9.59.. nombre (celui qui s'arrondit, mais il a la plus petite partie fractionnaire), mais, si vous commencez à prendre cela en compte, vous vous retrouverez avec une cinquantaine de règles distinctes :-)

Un autre moyen qui semble le plus "fidèle" est de garder un exécutant (non intégral) total de l'endroit où vous êtes et ronde que valeur. Par exemple, en utilisant les valeurs que vous avez donné:

Value      CumulValue  CumulRounded  Baseline  Need
---------  ----------  ------------  --------  ----
                                  0
13.626332   13.626332            14         0    14 ( 14 -  0)
47.989636   61.615968            62        14    48 ( 62 - 14)
 9.596008   71.211976            71        62     9 ( 71 - 62)
28.788024  100.000000           100        71    29 (100 - 71)
                                                ---
                                                100

À chaque étape, vous n'avez pas arrondir le nombre lui-même. Au lieu de cela vous autour de la valeur accumulée et faire le meilleur entier qui atteint cette valeur à partir de la ligne de base. Le niveau de référence est la valeur cumulative (arrondi) de la rangée précédente.

Cela fonctionne parce que vous êtes de ne pas perdre d'informations à chaque étape, mais plutôt à l'aide de l'information de manière plus intelligente. Les "bons" des valeurs arrondies sont dans la dernière colonne, et vous pouvez voir que leur somme soit égale à 100.

37voto

yonilevy Points 2106

Puisque aucune de ces réponses semblent, pour le résoudre correctement, voici mon semi-obscure version à l'aide de underscorejs:

function foo(l, target) {
    var off = target - _.reduce(l, function(acc, x) { return acc + Math.round(x) }, 0);
    return _.chain(l).
            sortBy(function(x) { return Math.round(x) - x }).
            map(function(x, i) { return Math.round(x) + (off > i) - (i >= (l.length + off)) }).
            value();
}

foo([13.626332, 47.989636, 9.596008, 28.788024], 100) // => [48, 29, 14, 9]
foo([16.666, 16.666, 16.666, 16.666, 16.666, 16.666], 100) // => [17, 17, 17, 17, 16, 16]
foo([33.333, 33.333, 33.333], 100) // => [34, 33, 33]
foo([33.3, 33.3, 33.3, 0.1], 100) // => [34, 33, 33, 0]

9voto

D Stanley Points 54768

NE PAS la somme des chiffres arrondis. Vous allez avoir des résultats inexacts. Le total pourrait être sensiblement en fonction du nombre de termes et de la distribution des fractions.

Affichage des nombres arrondis mais somme des valeurs réelles. Selon la façon dont vous avez présenté les chiffres, la façon de le faire serait de varier. De cette façon, vous obtenez

14
48
10
29
__
100

De toute façon vous allez, vous allez avoir de divergence. Il n'y a aucun moyen dans votre exemple de montrer des chiffres qui s'ajoutent à 100 sans "arrondi" une valeur de la mauvaise façon (moins l'erreur serait de changer 9.596 à 9)

MODIFIER

Vous devez choisir entre l'une des opérations suivantes:

  1. L'exactitude des éléments
  2. L'exactitude de la somme (si vous êtes à la sommation des valeurs arrondies)
  3. La cohérence entre les éléments arrondis et arrondis somme)

La plupart du temps lorsque vous traitez avec des pourcentages #3 est la meilleure option, car il est plus évident lorsque le total est égal à 101% que lorsque les éléments individuels ne sont pas un total de 100, et vous gardez les éléments individuels précis. "Arrondi" 9.596 à 9 est inexacte, à mon avis.

Pour expliquer ce que j'ai parfois ajouter une note de bas de page qui explique que les valeurs individuelles sont arrondis et peuvent ne pas totaliser 100% - quelqu'un qui comprend l'arrondissement devrait être en mesure de comprendre cette explication.

6voto

atkretsch Points 785

Vous pourriez essayer de garder la trace de votre erreur, en raison de l'arrondissement, et ensuite arrondi à l'encontre du grain si le cumul d'erreur est plus grande que la partie fractionnaire du nombre actuel.

13.62 -> 14 (+.38)
47.98 -> 48 (+.02 (+.40 total))
 9.59 -> 10 (+.41 (+.81 total))
28.78 -> 28 (round down because .81 > .78)
------------
        100

Vous ne savez pas si ce serait le travail en général, mais il semble un travail similaire si l'ordre est inversé:

28.78 -> 29 (+.22)
 9.59 ->  9 (-.37; rounded down because .59 > .22)
47.98 -> 48 (-.35)
13.62 -> 14 (+.03)
------------
        100

Je suis sûr qu'il y a des cas limites où cela peut briser, mais de toute approche va être au moins un peu arbitraire, puisque vous êtes essentiellement la modification de vos données d'entrée.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X