2009-11-07 24 views
3

Hier, j'ai posé une question à virgule flottante, et j'en ai une autre. Je fais des calculs où j'utilise les résultats des fonctions sinus, cosinus et tangente de math.h (langage C).Floating point again

L'un des développeurs a murmuré que vous devez faire attention aux valeurs de retour de ces fonctions et je ne devrais pas faire d'hypothèses sur les valeurs de retour des fonctions mathématiques gcc. Je n'essaie pas de lancer une discussion, mais je veux vraiment savoir ce que je dois faire attention lorsque je fais des calculs avec les fonctions mathématiques standard.

x

+1

Vous avez réussi à créer deux comptes. Votre question précédente a été posée en utilisant http://stackoverflow.com/users/205441/xofo. Envoyez un e-mail à [email protected] pour les faire fusionner. – ChrisF

+0

ne répondant pas exactement à votre question, mais si vous êtes sur gcc, vous pouvez essayer d'utiliser l'option -mfpmath = sse pour réduire les erreurs en virgule flottante. – int3

Répondre

3

Vous ne devriez pas supposer que les valeurs retournées seront conformes à des degrés élevés de précision entre les différentes versions compilateur/de stdlib.

C'est à peu près tout.

+0

C'est ce dont je me souviens avoir été dit. Donc, si je veux une plus grande précision, est-ce que j'utilise une autre bibliothèque mathématique, et laquelle? x – Xofo

+1

Si vous voulez vous assurer que différents compilateurs fourniront exactement les mêmes valeurs, alors vous devriez lancer vos propres fonctions sin/cos/tan au lieu d'utiliser les fonctions stdlib fournies par le fournisseur. Ou utilisez une bibliothèque tierce qui le fait. Naturellement, ces fonctions ne peuvent pas appeler d'autres routines stdlib. Vous pouvez également générer un ensemble de tables trigonométriques stockées en tant que fichier de données et vos routines sin/trig/cos seront des recherches. Je demanderais si c'est vraiment nécessaire? C'est quelque chose que j'ai dû faire par le passé mais ce n'est certainement pas commun. –

+1

Il n'y a pas grand-chose à faire. Netlib est assez standard http://www.netlib.org/fdlibm/ –

0

Le problème n'est pas avec les fonctions mathématiques standard, tant que la nature de l'arithmétique à virgule flottante.

Version très courte: ne comparez pas deux nombres à virgule flottante pour l'égalité, même avec des identités évidentes et triviales comme 10 == 10/3.0 * 3.0 ou tan(x) == sin(x)/cos(x).

1

Le point flottant est simple. Souvenez-vous toujours qu'il existe une composante d'incertitude pour toutes les opérations et fonctions en virgule flottante. Il est habituellement modélisé comme étant aléatoire, même si ce n'est généralement pas le cas, mais si vous le traitez comme aléatoire, vous réussirez à comprendre votre propre code. Par exemple:

a = a/3 * 3;

Cela devrait être traitée comme si elle était:

a = (a/3 + error1) * 3 + error2;

Si vous voulez une estimation de la taille des erreurs, vous devez creuser dans chaque opération/fonction pour le savoir. Différents compilateurs, choix de paramètres, etc. produiront des valeurs différentes. Par exemple, 0.09-0.089999 sur un système avec une précision de 5 chiffres produira une erreur entre -0.000001 et 0.000001. cette erreur est comparable en taille avec le résultat réel.

Si vous voulez apprendre à faire des virgules flottantes aussi précises que possible, alors c'est une étude à part.

+0

Non seulement ce n'est jamais aléatoire, mais votre réponse ne fournit vraiment aucune information valable. – rlbond

+0

C'est ainsi qu'il est enseigné à l'Université, si vous étudiez l'analyse numérique, qui est essentiellement les mathématiques des calculs à virgule flottante sur les ordinateurs. Les ingénieurs audio ne l'appellent pas des valeurs aléatoires, ils l'appellent «bruit», mais c'est la même idée. Mon message fournit les informations permettant aux programmeurs de comprendre, où les erreurs se produisent dans le code à virgule flottante, et quelle est la taille de l'erreur. En liant la taille des valeurs aléatoires au choix des compilateurs, la question d'origine est répondue. –

+1

Dans un environnement IEEE-754, il n'y a rien d'aléatoire sur le flottant. Le flottant n'est pas de la magie noire. La présence de l'arrondi n'implique pas le non-déterminisme. –

3

Vous ne devez pas vous attendre à ce que sin (PI/6) soit égal à cos (PI/3), par exemple. Vous ne devriez pas non plus vous attendre à ce que asin (sin (x)) soit égal à x, même si x est dans le domaine du péché. Ils seront proches, mais pourraient ne pas être égaux.

0

vous devez prendre soin de la précision:

  • Structure d'un nombre à virgule flottante
  • vous sur 32bits, 64 bits plate-forme?
  • vous devriez lire IEEE Standard for Binary Floating-Point Arithmetic
  • il existe quelques bibliothèques intersting telles GMP, ou MPFR.
  • vous devez savoir comment on compare les nombres à virgule flottante
  • etc ...
0

était d'accord avec toutes les réponses qui disent que vous ne devriez pas comparer l'égalité.Ce que vous pouvez faire, cependant, est de vérifier si les chiffres sont assez proches, comme ceci:

if (abs(numberA - numberB) < CLOSE_ENOUGH) 
{ 
    // Equal for all intents and purposes 
} 

CLOSE_ENOUGH est une petite valeur appropriée à virgule flottante.