2009-01-05 7 views
4

(exemples de code sont python)
laisse supposer que nous avons une liste des pourcentages qui ajoutent jusqu'à 100:algorithme de garder une liste des pourcentages d'ajouter jusqu'à 100%

mylist = [2.0, 7.0, 12.0, 35.0, 21.0, 23.0] 

Certaines valeurs de mylist peut être changé, d'autres doivent rester fixés.
Supposons que les 3 premiers (2.0, 7.0, 12.0) doivent rester fixes et que les trois derniers (35.0, 21.0, 23.0) peuvent être modifiés.

fix = mylist[:3] 
vari = mylist[3:] 

L'objectif est d'ajouter un nouvel élément à mylist, en somme (mylist) reste 100,0 et vari
articles gardent leurs relations les uns aux autres. Pour cela, nous devons soustraire un CERTAIN
POURCENTAGE de chaque élément vari. Exemple: Supposons que nous voulons ajouter 4.0 à Mylist.
En utilisant une boucle d'aproximation laide j'ai découvert que j'ai besoin de soustraire ca. 5,0634%
de chaque élément vari (CERTAIN POURCENTAGE = 5,0634):

adjusted =[] 
for number in vari: 
    adjusted.append(number-(number*(5.0634/100.0))) 
adjusted.extend(fix) 
adjusted.append(4.0) 

ajusté contient maintenant mon résultat souhaité.

Ma question est de savoir comment calculer CERTAINS POURCENTAGES;.)

+0

Juste comme une question rapide, voyez-vous des valeurs ajoutées comme entrant dans le "fix" ensemble ou le "vari" ensemble, par exemple. pouvez-vous modifier les valeurs que vous ajoutez? – chillysapien

+0

une valeur à ajouter est correctif pendant le processus d'être ajouté à la liste. son rôle dans mylist pourrait être fixe ou variable pour d'autres manipulations. – Titusz

Répondre

9

Comment ça?

def adjustAppend(v, n): 
    weight= -n/sum(v) 
    return [ i+i*weight for i in v ] + [n] 

donné une liste des numéros v, ajoutez un nouveau numéro, n. Pondérer le nombre existant pour conserver la même somme.

sum(v) == sum(v + [n]) 

Chaque élément de v, i, doit être réduit par une fonction de i, r (i) de telle sorte que

sum(r(i)) == -n 

ou

sum(map(r, v)) == -n 

Par conséquent, la fonction de pondération est -(n*i)/sum(v)

+0

L'ajustement constant des valeurs flottantes entraîne une accumulation d'erreurs d'arrondi. Gardez une trace de qui sont absolus et qui sont des valeurs relatives (en unités, comme px vs% en CSS) et lors du calcul des valeurs finales, ajustez-les dans les résultats, pas le stockage. – ironfroggy

+0

@ironfroggy: Vous avez raison. Imaginez que le cas d'utilisation implique une séquence arbitraire d'ajouts et de suppressions. Chaque numéro pourrait alors avoir un ajustement assez complexe en fonction de l'historique des changements. Ce serait trop complexe pour le gain de précision qui en résulte. –

+0

J'ai implémenté ceci, et ça marche bien. Pour résoudre le problème d'arrondi, nous pourrions définir: En faveur de la somme (v) étant exactement 100.0, il serait bon que les relations entre les éléments soient à peu près les mêmes;) – Titusz

3

vous être stupide.

Supposons que vous vouliez ajouter la valeur 4.0 à la liste. Vous n'avez pas besoin de soustraire un certain montant de chacun. Ce que vous devez faire est de multiplier chaque élément.

100-4 = 96. donc, il faut multiplier chaque élément par 0,96

vous voulez ajouter 20,0 comme un élément. alors vous multipliez chaque élément de 0,8, ce qui est (100-20) * 0,01

mise à jour: Hrmn Je n'ai pas lu assez attentivement.

Pensez-y comme ça. (fixe) + (vari) = 100; (fixe) + (vari * x) + newitem = 100;

donc fondamentalement comme ce que nous avons fait auparavant, sauf avec la partie variable. si vari totalise 50, et que le nouvel article que vous ajoutez est 3.0, alors multipliez chaque article en vari par (47/50)

+0

100 - 4 = 94? 96? ;) –

+0

Aussi, il ne peut pas soustraire. La technique est bonne cependant. –

+0

d'oh. Tard dans la nuit. ne devrait pas faire de maths quand je suis fatigué. – Breton

1
NEW_NUMBER = 4.0 

mylist = [2.0, 7.0, 12.0, 35.0, 21.0, 23.0] 
fix = mylist[:3] 
vari = mylist[3:] 

weight = (100 - sum(fix) - NEW_NUMBER)/sum(vari) 

adjusted = [] 
adjusted.extend((weight*v for v in vari)) 
adjusted.extend(fix) 
adjusted.append(NEW_NUMBER) 

print sum(adjusted)    # 100.0 

Edit: Triptyque est juste, si vous êtes réellement intéressé par le certain pourcentage, le code suivant va pour elle:

certain_percentage = 100 * NEW_NUMBER/sum(vari) 
print certain_percentage  # 5.06329113924 

Je pense que votre constante 5.0634 devrait effectivement être 5.0633.

2
new_item = 4.0 
CERTAIN_PERCENTAGE = 100 * (float(new_item)/sum(vari)) 
+0

belle et courte réponse;.) Merci ... – Titusz

+0

Merci. C'est exactement ce que vous avez demandé, mais ne manquez pas les autres bonnes réponses ici. – Triptych

Questions connexes