2010-10-28 40 views
0

Je fais de l'arithmétique en virgule flottante et j'ai des problèmes de précision. La valeur résultante est différente sur deux machines pour la même entrée. J'ai lu le poste @Why can't I multiply a float? et aussi lu d'autres documents sur le web & compris qu'il s'agit de la représentation binaire de virgule flottante et sur la machine epsilon. Cependant, je voulais vérifier s'il y avait un moyen de résoudre ce problème/Certains travaillent pour l'arithmétique en virgule flottante en C++ ?? Je convertis un flotteur en short non signé pour le stockage et suis en train de convertir en cas de besoin. Cependant, quand je le convertis en short non signé, la précision (à 6 décimales) reste correcte sur une machine mais échoue sur l'autre.Existe-t-il une solution pour les problèmes arithmétiques à virgule flottante en C++?

//convert FLOAT to short 

unsigned short sConst = 0xFFFF; 

unsigned short shortValue = (unsigned short)(floatValue * sConst); 

//Convert SHORT to FLOAT 

float floatValue = ((float)shortValue/sConst); 
+2

Quel est exactement le problème?Le simple fait que le résultat de la multiplication soit légèrement différent sur deux machines différentes n'est pas un problème en soi. Pourquoi cela en constitue-t-il un pour vous? –

+0

Puisqu'il n'y a aucun problème réel indiqué, cette question ne peut pas être répondue correctement. Voter pour fermer n'est pas une vraie question. –

+0

a mis à jour la question! –

Répondre

2

Un short doit être d'au moins 16 bits et dans beaucoup d'implémentations c'est exactement ce que c'est. Un unsigned 16 bits short contiendra des valeurs comprises entre 0 et 65535. Cela signifie qu'un raccourci ne contiendra pas cinq chiffres complets de précision, et certainement pas six. Si vous voulez six chiffres, vous avez besoin de 20 bits. Par conséquent, toute perte de précision est probablement due au fait que vous essayez d'insérer six chiffres de précision en quelque chose de moins de cinq chiffres. Il n'y a pas de solution à cela, autre que d'utiliser un type intégral qui prend probablement autant de stockage qu'un float.

Je ne sais pas pourquoi cela semblerait fonctionner sur un système donné. Étiez-vous en utilisant les mêmes numéros sur les deux? Avez-vous utilisé un système à virgule flottante plus ancien, et un qui a coïncidence donné les résultats que vous attendiez sur les échantillons que vous avez essayés? Était-il possible d'utiliser un plus grand short que l'autre?

1

Si vous voulez utiliser des types à virgule flottante natif, le meilleur que vous pouvez faire est d'affirmer que la sortie des valeurs par votre programme ne ne diffère pas trop d'un ensemble de valeurs de référence.

La définition précise de "trop" dépend entièrement de votre application. Par exemple, si vous calculez a + b sur différentes plates-formes, vous devriez trouver les deux résultats dans la précision de la machine l'un par rapport à l'autre. D'un autre côté, si vous faites quelque chose de plus compliqué comme l'inversion de matrice, les résultats diffèreront probablement plus que la précision de la machine. Déterminer précisément à quel point vous pouvez vous attendre à ce que les résultats se ressemblent est un processus très subtil et compliqué. À moins de savoir exactement ce que vous faites, il est probablement plus sûr (et plus sain) de déterminer la précision dont vous avez besoin en aval dans votre application et de vérifier que le résultat est suffisamment précis.

Pour avoir une idée sur la façon de calculer l'erreur relative entre deux valeurs à virgule flottante avec vigueur, voir cette réponse et le guide à virgule flottante lié dans celui-ci:

Floating point comparison functions for C#

+0

Merci philip pour la réponse! mis à jour la question –

0

Au lieu d'utiliser 0xFFFF, utilisez-en la moitié, c'est-à-dire 32768 pour la conversion. 32768 (Ox8000) a une représentation binaire de 1000000000000000 alors que OxFFFF a une représentation binaire de 1111111111111111. La représentation binaire de Ox8000 implique clairement, la multiplication & divsion opérations pendant la conversion (à court (ou) lors de la conversion en flottant) ne changera pas les valeurs de précision après zéro. Pour une conversion latérale, OxFFFF est préférable, car il conduit à un résultat plus précis.