Question

Lorsque la racine carrée inverse d'un double, est-il préférable de bloquer invalides entrées non positives à 0,0 ou MIN_DBL? (Dans mon exemple ci-dessous double b peut finir par être négatif en raison à des erreurs d'arrondi en virgule flottante et parce que les lois de la physique sont légèrement un peu trafiqué dans le jeu.)

Les deux division par 0,0 et MIN_DBL produire le même résultat dans le jeu parce que 1/0.0 et 1/DBL_MIN sont effectivement infini. Mon intuition dit MIN_DBL est le meilleur choix, mais aurait-il des cas pour l'utilisation 0.0? Comme peut-être sqrt(0.0), 1/0.0 et multiplication par 1.#INF000000000000 exécutent plus rapidement parce qu'ils sont des cas particuliers.

double b = 1 - v.length_squared()/(c*c);

#ifdef CLAMP_BY_0
if (b < 0.0) b = 0.0;
#endif

#ifdef CLAMP_BY_DBL_MIN
if (b <= 0.0) b = DBL_MIN;
#endif

double lorentz_factor = 1/sqrt(b);

à double division MSVC:

1/0.0     = 1.#INF000000000000
1/DBL_MIN = 4.4942328371557898e+307
Était-ce utile?

La solution

Lorsque vous traitez avec les mathématiques à virgule flottante, « l'infini » et « efficacement l'infini » sont tout à fait différents. Une fois qu'un numéro cesse d'être fini, il a tendance à rester. Ainsi, alors que la valeur de lorentz_factor est « efficace » même pour les deux méthodes, selon la façon dont vous utilisez cette valeur, les calculs ultérieurs peuvent être radicalement différents. sqrt(lorentz_factor) pour restes d'exemple infini si vous pince à 0, mais sera calculée en fait, si vous Clamp à un nombre très très faible.

La réponse dépendra en grande partie de ce que vous envisagez de faire avec cette valeur une fois que vous avez serré il.

Autres conseils

Pourquoi ne pas simplement assign INF à lorentz_factor directement, évitant à la fois l'appel sqrt et la division?

double lorentz_factor;
if (b <= 0.0) 
    lorentz_factor = std::numeric_limits<double>::infinity();
else
    lorentz_factor = 1/sqrt(b);
  • Vous devrez #include <limits> pour cela.
  • Vous pouvez également utiliser ::max() au lieu de ::infinity(), si c'est ce dont vous avez besoin.
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top