2010-11-20 7 views
4

J'ai cette fonction pour limiter une rotation à la gamme de 0,0 à 360,0:Comment limiter un nombre à une gamme

private float ClampRotation(float rotation) { 

    while(rotation < 0.0f) rotation += 360.0f; 
    while(rotation >= 360.0f) rotation -= 360.0f; 

    return rotation; 

} 

Cette fonction fonctionne très bien et il ne peut probablement pas être plus efficace, mais je Je me demandais juste s'il y a une fonction Java native qui peut faire la même chose? Le plus proche est Math.min/max, mais cela ne fonctionne pas comme cela. Une rotation de -10.0 devrait produire 350.0 et non 0.0 comme min/max ferait.

+0

Ce n'est certainement pas la solution la plus efficace: plus le nombre est grand, plus la boucle est longue. – tdammers

+0

"Ne peut pas être plus efficace", il peut être énormément plus efficace pour de grandes valeurs de rotation, comme le prouve la réponse @Paul. –

Répondre

4

% (module) fonctionne sur des valeurs à virgule flottante utilisent donc rotation % 360.0f (vous devrez ajouter 360.0 après aux nombres négatifs)

+0

L'opérateur de module vérifie simplement si deux nombres sont divisibles uniformément ... Je ne suis pas sûr de savoir comment cela va aider avec la question de l'OP. –

+3

@willell: en fait, il renvoie le * reste * quand un nombre est divisé par l'autre - quand il est nul, ils sont exactement divisibles. – SimonJ

3

il est juste des maths .. vous pouvez le faire comme ceci:

private float ClampRotation(float rotation) { 

    return rotation+360.0f*Math.ceil(-rotation/360.0f); 

} 

Je suis assez sûr que c'est OK

+2

Je pense que vous venez d'inventer l'opérateur '%';) – SimonJ

+0

c'est en fait le contraire (trouver combien de fois 'rotation' est en 360. modulo trouve le reste) (btw - vous avez toujours raison quand vous dites qu'il peut être fait avec% à la place.pour une raison que je préfère cela ..) – RoeeK

+0

Non, c'est une variante de "floored division" modulo (voir http://en.wikipedia.org/wiki/Modulo_operation). Rien de mal à cela - cela a fonctionné pour Knuth! – SimonJ

4

Utilisez l'opérateur de module, puis comptez pour les valeurs inférieures à 0;

private float ClampRotation(float rotation) { 

    rotation = rotation % 360f; 

    if (rotation < 0f) rotation += 360f; 

    return rotation; 

} 
1

Vous avez la mise en œuvre traditionnelle des angles d'enveloppement qui sont inférieurs à un ordre de grandeur de la plage souhaitée. Le module est un peu bizarre pour le virgule flottante - il devient négatif pour le négatif, donc vous devez toujours avoir une branche, et cela implique une division, qui est plus lente sur certaines machines (comme je n'ai pas trouvé de machine où% est significativement moins cher que de faire le tour d'une boucle avec quelques soustractions deux ou trois fois).

Si vos valeurs sont comprises entre -1000 et +1000, votre version est à la fois plus claire et plus rapide. Si vos valeurs sont plus larges que cela, optez pour une version basée sur le module. Si c'est très important, testez les deux sur votre matériel avec les plages de valeurs que vous allez utiliser.

Questions connexes