107 votes

Mathématiques - cartographie des nombres

Comment faire correspondre des nombres, linéairement, entre a et b pour aller entre c et d.

C'est-à-dire que je veux que les nombres entre 2 et 6 correspondent aux nombres entre 10 et 20... mais j'ai besoin du cas généralisé.

Mon cerveau est grillé.

5 votes

224voto

PeterAllenWebb Points 4731

Si votre nombre X se situe entre A et B, et que vous souhaitez que Y se situe entre C et D, vous pouvez appliquer la transformation linéaire suivante :

Y = (X-A)/(B-A) * (D-C) + C

Cela devrait vous donner ce que vous voulez, bien que votre question soit un peu ambiguë, puisque vous pourriez aussi mapper l'intervalle dans le sens inverse. Faites simplement attention à la division par zéro et tout devrait bien se passer.

19 votes

Pour plus de clarté, je préfère new_value = (old_value - old_bottom) / (old_top - old_bottom) * (new_top - new_bottom) + new_bottom ;

2 votes

Existe-t-il une dérivation de cette équation quelque part ?

0 votes

@shaveenk c'est l'équation d'une ligne, avec Y=f(X)=m*X+b où m et b ont été déterminés simultanément à partir des deux équations de contraintes suivantes qui résultent de la substitution des valeurs de X et Y aux points d'extrémité requis : C=m*A+b et D=m*B+b

23voto

Konrad Rudolph Points 231505

Divisez pour obtenir le rapport entre les tailles des deux gammes, puis soustrayez la valeur de départ de votre gamme initiale, multipliez par le rapport et ajoutez la valeur de départ de votre deuxième gamme. En d'autres termes,

R = (20 - 10) / (6 - 2)
y = (x - 2) * R + 10

Cela permet de répartir uniformément les chiffres de la première tranche dans la deuxième tranche.

0 votes

Cela ne fonctionne pas. Ma plage est de 1000000000 à 9999999999 et les chiffres peuvent être compris entre 1 et 999999999.

0 votes

@Odelya Bien sûr que ça marche. C'est une transformation mathématique assez simple. Il suffit d'utiliser un type de nombre suffisamment grand (bignum ou similaire). Vos nombres sont simplement trop grands pour des entiers de 32 bits - mais des entiers de 64 bits par exemple fonctionneront.

0 votes

Ils sont de type double. double R = (20 - 10) / (6 - 2) ; double y = (X - 2) * R + 10 ;

4voto

Metro Points 764

Soit dit en passant, il s'agit du même problème que la classique conversion de Celcius en Farenheit, où l'on veut faire correspondre une plage de nombres qui équivaut à 0 - 100 (C) à 32 - 212 (F).

0 votes

En quoi est-ce une réponse ?

0 votes

C'est un exemple de l'application de la question. Beaucoup ont ce problème simple dans les cours d'introduction à la CS et ne considèrent pas que la solution peut être généralisée à d'autres problèmes. J'essayais d'ajouter un contexte à la question originale. La question initiale avait déjà reçu une réponse adéquate.

1voto

PhiLho Points 23458
int srcMin = 2, srcMax = 6;
int tgtMin = 10, tgtMax = 20;

int nb = srcMax - srcMin;
int range = tgtMax - tgtMin;
float rate = (float) range / (float) nb;

println(srcMin + " > " + tgtMin);
float stepF = tgtMin;
for (int i = 1; i < nb; i++)
{
  stepF += rate;
  println((srcMin + i) + " > " + (int) (stepF + 0.5) + " (" + stepF + ")");
}
println(srcMax + " > " + tgtMax);

Avec des contrôles sur la division par zéro, bien sûr.

1voto

Chris Cudmore Points 11133

Chaque intervalle d'unité sur la première plage occupe (d-c)/(b-a) "l'espace" sur la seconde plage.

Pseudo :

var interval = (d-c)/(b-a)
for n = 0 to (b - a)
    print c + n*interval

La façon dont vous gérez les arrondis vous appartient.

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