Les mathématiques n'ont jamais été mon fort à l'école :(
int input_start = 0; // The lowest number of the range input.
int input_end = 254; // The lowest number of the range input.
int output_start = 500; // The lowest number of the range output.
int output_end = 5500; // The largest number of the range ouput.
int input = 127; // Input value.
int output = 0;
Comment puis-je convertir la valeur d'entrée en la valeur de sortie correspondante de cette plage?
Par exemple, une valeur d'entrée de "0" équivaudrait à une valeur de sortie de "500", une valeur d'entrée de "254" serait égale à une valeur de sortie de "5500". Je ne peux pas comprendre comment calculer une valeur de sortie si une valeur d'entrée est disons 50 ou 101.
Je suis sûr que c'est simple, je ne peux pas penser en ce moment :)
Edit: j'ai juste besoin de nombres entiers, pas de fractions ou quoi que ce soit.
Oublions les mathématiques et essayons de résoudre cela intuitivement.
Tout d'abord, si nous voulons mapper les numéros d'entrée dans la plage [0
, x
] à la plage de sortie [0
, y
], nous avons juste besoin de l'échelle d'un montant approprié. 0 va à 0, x
va à y
, et un nombre t
ira à (y/x)*t
.
Donc, réduisons votre problème au problème plus simple ci-dessus.
Une plage d'entrée de [input_start
, input_end
] A input_end - input_start + 1
Nombres. C'est donc l'équivalent d'une plage de [0
, r
], où r = input_end - input_start
.
De même, la plage de sortie est équivalente à [0
, R
], où R = output_end - output_start
.
Une entrée de input
équivaut à x = input - input_start
. Cela, du premier paragraphe se traduira par y = (R/r)*x
. Ensuite, nous pouvons traduire la valeur y
dans la plage de sortie d'origine en ajoutant output_start
: output = output_start + y
.
Cela nous donne:
output = output_start + ((output_end - output_start) / (input_end - input_start)) * (input - input_start)
Ou, d'une autre manière:
/* Note, "slope" below is a constant for given numbers, so if you are calculating
a lot of output values, it makes sense to calculate it once. It also makes
understanding the code easier */
slope = (output_end - output_start) / (input_end - input_start)
output = output_start + slope * (input - input_start)
Maintenant, étant C et la division en C tronquée, vous devriez essayer d'obtenir une réponse plus précise en calculant les choses en virgule flottante:
double slope = 1.0 * (output_end - output_start) / (input_end - input_start)
output = output_start + slope * (input - input_start)
Si vous voulez être encore plus correct, vous feriez un arrondi au lieu de la troncature à l'étape finale. Vous pouvez le faire en écrivant une simple fonction round
:
#include <math.h>
double round(double d)
{
return floor(d + 0.5);
}
Ensuite:
output = output_start + round(slope * (input - input_start))
Arduino a ce intégré comme carte .
Exemple:
/* Map an analog value to 8 bits (0 to 255) */
void setup() {}
void loop()
{
int val = analogRead(0);
val = map(val, 0, 1023, 0, 255);
analogWrite(9, val);
}
Il a également l'implémentation sur cette page:
long map(long x, long in_min, long in_max, long out_min, long out_max)
{
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
Le point crucial ici est de faire la division entière (qui inclut l'arrondi) au bon endroit. Jusqu'à présent, aucune des réponses n'a donné les bonnes parenthèses. Voici la bonne façon:
int input_range = input_end - input_start;
int output_range = output_end - output_start;
output = (input - input_start)*output_range / input_range + output_start;
la formule est
f (x) = (x - start_start)/(input_end - input_start) * (output_end - output_start) + output_start
Je vais brancher ce post ici: https://betterexplained.com/articles/rethinking-arithmetic-a-visual-guide/ car cela m'a beaucoup aidé en essayant de trouver cela intuitivement . Une fois que vous avez compris ce que dit le message, il est trivial de trouver ces formules par vous-même. Notez que j'avais aussi du mal avec de telles questions. (Je n'ai aucune affiliation - je l'ai trouvé très utile)
disons que vous avez la plage [input_start..input_end]
, commençons par la normaliser de telle sorte que 0 soit input_start
et 1 soit input_end
. il s'agit d'une technique simple pour faciliter le problème.
comment fait-on cela? nous allons devoir changer tout ce qui reste par input_start, de telle sorte que si l'entrée x se trouve être input_start
, elle devrait donner zéro.
alors, disons que f(x)
est la fonction qui effectue la conversion.
f(x) = x - input_start
essayons:
f(input_start) = input_start - input_start = 0
fonctionne pour input_start
.
à ce stade, cela ne fonctionne pas encore pour input_end
, car nous ne l'avons pas mis à l'échelle.
disons simplement la réduire de la longueur de la plage, puis nous aurons la plus grande valeur (input_end) mappée à une.
f(x) = (x - input_start) / (input_end - input_start)
ok, essayons avec input_end
.
f (input_end) = (input_end - input_start) / (input_end - input_start) = 1
génial, semble fonctionner.
ok, prochaine étape, nous allons le mettre à l'échelle pour la plage de sortie. C'est aussi trivial que de simplement multiplier par la longueur réelle de la plage de sortie, en tant que telle:
f(x) = (x - input_start) / (input_end - input_start) * (output_end - output_start)
maintenant, en fait, nous avons presque terminé, il nous suffit de le déplacer vers la droite pour que 0 commence à partir de output_start.
f(x) = (x - input_start) / (input_end - input_start) * (output_end - output_start) + output_start
essayons rapidement.
f(input_start) = (input_start - input_start) / (input_end - input_start) * (output_end - output_start) + output_start
vous voyez que la première partie de l'équation est à peu près multipliée par zéro, annulant ainsi tout, vous donnant
f(input_start) = output_start
essayons aussi input_end
.
f(input_end) = (input_end - input_start) / (input_end - input_start) * (output_end - output_start) + output_start
qui à son tour finira par:
f(input_end) = output_end - output_start + output_start = output_end
comme vous pouvez le voir, il semble maintenant être correctement cartographié.
output = ((input - input_start)/(input_end - input_start)) * (output_end - output_start) + output_start
Ce que cela fait, c'est de découvrir proportionnellement "dans quelle mesure" la plage d'entrée de l'entrée est. Il applique ensuite cette proportion à la taille de la plage de sortie pour déterminer en termes absolus dans quelle mesure la sortie doit être dans la plage de sortie. Il ajoute ensuite le début de la plage de sortie pour obtenir le numéro de sortie réel.