Disons que j'ai un tableau de nombres à virgule flottante, dans un ordre trié (disons ascendant), dont la somme est connue pour être un entier. N
. Je veux "arrondir" ces nombres en nombres entiers tout en laissant leur somme inchangée. En d'autres termes, je cherche un algorithme qui convertit le tableau de nombres à virgule flottante (que j'appelle fn
) à un tableau d'entiers (appelé in
) tel que :
- les deux tableaux ont la même longueur
- la somme du tableau d'entiers est
N
- la différence entre chaque nombre à virgule flottante
fn[i]
et son entier correspondantin[i]
est inférieur à 1 (ou égal à 1 si vous y tenez vraiment) - étant donné que les flottants sont dans l'ordre trié (
fn[i] <= fn[i+1]
), les entiers seront également dans l'ordre trié (in[i] <= in[i+1]
)
Si ces quatre conditions sont satisfaites, un algorithme qui minimise la variance d'arrondi ( sum((in[i] - fn[i])^2)
) est préférable, mais ce n'est pas un gros problème.
Exemples :
\[0.02, 0.03, 0.05, 0.06, 0.07, 0.08, 0.09, 0.1, 0.11, 0.12, 0.13, 0.14\]
=> \[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1\]
\[0.1, 0.3, 0.4, 0.4, 0.8\]
=> \[0, 0, 0, 1, 1\]
\[0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1\]
=> \[0, 0, 0, 0, 0, 0, 0, 0, 0, 1\]
\[0.4, 0.4, 0.4, 0.4, 9.2, 9.2\]
=> \[0, 0, 1, 1, 9, 9\] is preferable
=> \[0, 0, 0, 0, 10, 10\] is acceptable
\[0.5, 0.5, 11\]
=> \[0, 1, 11\] is fine
=> \[0, 0, 12\] is technically not allowed but I'd take it in a pinch
Pour répondre à d'excellentes questions soulevées dans les commentaires :
- Les éléments répétés sont autorisés dans les deux tableaux (mais je serais également intéressé de connaître les algorithmes qui ne fonctionnent que si le tableau de flottants ne comprend pas de répétitions).
- Il n'y a pas de réponse correcte unique - pour un tableau d'entrée donné de flottants, il existe généralement plusieurs tableaux d'ints qui satisfont aux quatre conditions.
- L'application que j'avais en tête était - et c'est un peu bizarre - la distribution de points aux premiers arrivés dans une partie de MarioKart ;-) Je n'ai jamais joué au jeu moi-même, mais en regardant quelqu'un d'autre, j'ai remarqué qu'il y avait 24 points répartis entre les 4 premiers, et je me suis demandé comment il serait possible de distribuer les points en fonction du temps d'arrivée (ainsi, si quelqu'un termine avec une grande avance, il obtient une plus grande part des points). Le jeu enregistre les totaux de points sous forme d'entiers, d'où la nécessité de ce type d'arrondi.
Pour les curieux, voici le test script que j'utilisais pour identifier les algorithmes qui fonctionnaient.
0 votes
Vous voulez séparer la partie fractionnaire d'un tableau de flottants ?
0 votes
Que se passe-t-il si vous avez un tableau de 1000 .001 ? Comment voulez-vous qu'il se comporte ? Les répétitions sont-elles autorisées ?
0 votes
Réfléchissez à nouveau à vos exemples. Seul le premier montre vraiment quelle est votre question.
2 votes
@ojblass : dans ce cas, vous arrondissez 999 d'entre eux à 0, puis vous arrondissez le dernier à 1. Cela répondrait à l'exigence.
0 votes
Dans votre premier exemple : Pourquoi 0,14 serait-il arrondi à 1 ?
0 votes
@Brian : pour satisfaire son exigence. Arrondir tous les nombres naturellement, puis trouver la différence nécessaire pour faire la somme et arrondir dans ce sens.
0 votes
Je suis curieux de connaître le contexte : dans quel type de problème avez-vous besoin de ce comportement ?
0 votes
La règle 3 est étroitement liée à la règle 2, donc je suppose que vous ne pouvez pas avoir [0.01 0.04] et N=10 ? Qui définit la somme ?
4 votes
J'ai vu que cela était nécessaire dans des applications (logiciels d'estimation) où tout est arrondi en dollars et où les chiffres de la ligne de fond doivent correspondre.
0 votes
@Groo : les flottants sont calculés de manière à ce que leur somme soit un entier.
0 votes
@Jérôme : merci, j'ai modifié les exemples, ils devraient être un peu plus descriptifs maintenant.
0 votes
Voici une question connexe : stackoverflow.com/questions/3611015/
1 votes
Une autre question connexe : stackoverflow.com/questions/13483430/