2009-08-24 7 views
4

Je suis en train d'écrire du code iPhone qui reconnaît fuzzily si une ligne balayée est droite-ish. J'obtiens le relèvement des deux extrémités et je le compare à 0, 90, 180 et 270 degrés avec une tolérance de 10 degrés plus ou moins. En ce moment je le fais avec un tas de blocs si, ce qui semble super maladroit.Comment puis-je déterminer si un nombre est dans un pourcentage d'un autre nombre?

pour l'écriture d'une fonction qui, compte tenu de la portant 0..360, la tolérance pourcentage (par exemple 20% = (-10 ° à + 10 °)) et un angle droit comme 90 degrés , retourne si le roulement est dans la tolérance?

Mise à jour:Je suis peut-être trop spécifique. Je pense qu'une bonne fonction générale qui détermine si un nombre est dans un pourcentage d'un autre nombre a une utilité dans de nombreux domaines.

Par exemple: Est-ce le nombre swipeLength dans les 10% de maxSwipe? Ce serait utile.

BOOL isNumberWithinPercentOfNumber(float firstN, float percent, float secondN) { 
     // dunno how to calculate 
} 

BOOL result; 

float swipeLength1 = 303; 
float swipeLength2 = 310; 

float tolerance = 10.0; // from -5% to 5% 
float maxSwipe = 320.0; 

result = isNumberWithinPercentOfNumber(swipeLength1, tolerance, maxSwipe); 
// result = NO 

result = isNumberWithinPercentOfNumber(swipeLength2, tolerance, maxSwipe); 
// result = YES 

Voyez-vous ce que je veux dire?

+0

Les angles sont-ils différenciés à 180 degrés, par exemple, une ligne verticale tracée de haut en bas 90 et la même ligne tirée de bas en haut 270, ou sont-ils identiques? –

+1

Voulez-vous vraiment dire que la tolérance est un pourcentage? Pourcentage de quoi? Je pense qu'une simple différence angulaire a plus de sens en tant que seuil. –

+1

Une question connexe: http://stackoverflow.com/questions/338762/how-do-you-calculate-the-angle-between-two-normals-in-glsl (ceci montre comment calculer l'angle entre deux vecteurs) . –

Répondre

0

20% comme une décimale est égale à 0,2. Il suffit de diviser par 100.0 pour obtenir la décimale. Diviser par 2,0 pour obtenir la moitié de la plage acceptable. (Combiné en diviseur 200.0)

Ensuite, ajoutez et soustrayez 1,0 pour obtenir les valeurs 90% et 110%. Si le premier nombre est entre les plages, alors vous l'avez.

BOOL isNumberWithinPercentOfNumber(float firstN, float percent, float secondN) { 
     float decimalPercent = percent/200.0; 
     float highRange = secondN * (1.0 + decimalPercent); 
     float lowRange = secondN * (1.0 - decimalPercent); 
     return lowRange <= firstN && firstN <= highRange; 
} 

Remarque: il n'y a pas de vérification d'erreur ici pour les valeurs NaN ou négatives. Vous voudrez ajouter cela pour le code de production.

Mise à jour: pour faire en sorte que le pourcentage comprenne à la fois la plage +/-.

+0

Je n'ai pas précisé que si la tolérance est de 20%, cela signifie que la plage va de -10% à + 10% Mes excuses – willc2

+0

D'accord, il suffit de diviser par 200.0 au lieu de 100.0 –

+0

Cela ne fonctionne pas avec deux nombres négatifs. Par exemple, si vous passez en -20 et -20, cela retourne faux. – rolls

4
int AngularDistance (int angle, int targetAngle) 
{ 

    int diff = 0; 
    diff = abs(targetAngle - angle) 

    if (diff > 180) diff = 360 - diff; 

    return diff; 
} 

Ceci devrait fonctionner pour deux angles quelconques.

+0

Quelle question répondez-vous? – willc2

+0

Ceci est pour la question originale sur la comparaison d'un relèvement à une cible roulement (0 °, 90 °, 180 °, 270 °) La fonction vous donne l'angle entre les deux, que vous pouvez comparer à votre tolérance, disons 10 ° Comme l'a souligné Jim Lewis, les pourcentages ont peu de sens pour les angles, et ils sont généralement un peu plus compliqués (en raison de leur circularité: par exemple 350 ° + 20 ° = 10 °) –

0

Réponse à votre/nouvelle question raffinée:

bool isNumberWithinPercentOfNumber (float n1, float percentage, float n2) 
{ 

if (n2 == 0.0) //check for div by zero, may not be necessary for float 
    return false; //default for a target value of zero is false 
else 
    return (percentage > abs(abs(n2 - n1)/n2)*100.0); 
} 

Pour expliquer, vous prenez la différence absolue entre votre test et la valeur cible, et le diviser par la valeur cible (les deux « abs'olute appels font assurez-vous que cela fonctionne avec des nombres de cibles et de tests négatifs, mais pas avec des pourcentages/tolérances négatifs). Cela vous donne le pourcentage de la différence exprimée en fraction décimale, multiplie-le par 100 pour donner l'expression «commune» du pourcentage (10% = 0,10),

Questions connexes