2010-01-08 3 views
0

problème Simimilar à Math.Atan2 or class instance problem in C# et add two double given wrong resultmaintien double variable valeur incorrecte

Il est quelque chose que les lignes simples:

public static String DegreeToRadianStr(Double degree) 
    { 
     Double piBy180 = (Math.PI/180); 

     Double Val = (piBy180 * degree); // Here it is giving wrong value 
    } 

piBy180 * degré = -3,1415926535897931 mais Val = -3,1415927410125732

alt text http://www.imagechicken.com/uploads/1262936639009840000.jpg Je n'ai vraiment aucune idée quoi faire .. S'il vous plaît poser quelques questions à ce sujet, afin que je puisse signaler où il va mal.

Il est étonnant que piBy180 garde une valeur correcte.

Même chose se passe avec d'autres fonctions aussi, Mais certains comment j'ai manipulé pour obtenir des valeurs correctes. J'utilise C# .net SP1 de MS Visual Studio.

+4

Ici nous allons à nouveau ...... – leppie

+0

Pendant ce temps, j'ai changé Double à Decimal .. Voyons voir ce qui se passe. Jusqu'à maintenant semble OK. – Rick2047

+1

décimal est comme 20x plus lent que le double –

Répondre

0

Ce pourrait simplement être une erreur d'arrondi, mais je ne peux pas être sûr.

Consultez cet article sur l'arithmétique en virgule flottante. C'est écrit pour fortran, mais c'est toujours utile. http://www.lahey.com/float.htm

2

Il pourrait s'agir simplement d'un problème de formatage de chaîne. Essayez d'ajouter la ligne:

Debug.Assert(Val == (piBy180 * degree), "WTF?"); 

après l'affectation. Il ne devrait pas échouer, car ils sont tous les deux doubles, et les opérations arithmétiques sur eux devraient produire la même valeur binaire.

+0

Je suis d'accord, il pourrait s'agir d'un problème d'affichage. – redjackwong

+2

Vous devriez éviter de comparer les doubles avec l'égalité. Il se peut que 'value! = (Value/constant) * constant' (pour certaines 'value' et 'constante' en raison d'erreurs d'arrondi). –

+0

Ok, appris la nouvelle chose ici. – Rick2047

3

Il serait utile que vous nous avez dit la valeur de degree alors nous pourrions essayer de reproduire le problème ...

Trois choses:

  • Vous devez vous attendre une certaine quantité d'erreur virgule flottante arithmétique. Je ne m'attendrais pas à cela, mais ne vous attendez pas à voir une valeur exacte.
  • Les conversions de chaînes ne vous indiquent généralement pas la valeur exacte. J'ai un fichier - DoubleConverter.cs - avec une méthode ToExactString qui peut aider à diagnostiquer ce genre de chose.
  • Votre application utilise-t-elle DirectX? Cela peut changer le mode de processeur pour utiliser efficacement l'arithmétique 32 bits même lorsque vous avez des doubles dans votre code. Cela me semble être la cause la plus probable du problème, mais ce n'est encore qu'une supposition.

EDIT: Ok, donc il semble que j'ai deviné juste, et DirectX est probablement la cause. Vous pouvez passer CreateFlags.FpuPreserve au Device constructor pour l'éviter. Cela réduira les performances de DirectX, certes - mais c'est un compromis que vous devrez considérer par vous-même.

+0

Il est -180 de ce que je peux dire :) – leppie

+0

@leppie: C'était aussi mon estimation, et l'exécution du code donné donne la bonne réponse pour -180 ... mais ce serait bien d'en être sûr. –

+0

Cela n'a cependant rien à voir avec les mathématiques en virgule flottante, puisqu'il compare le côté droit au côté gauche du débogueur. Mathématiques à virgule flottante a une erreur, mais c'est une erreur déterministe ... –

0

Cela ne semble pas possible.

La valeur du degré piBy180 * est calculée presque correctement, à moins de 2 unités dans le 17ème chiffre significatif.Le processeur doit effectuer une multiplication pour ce faire, et il l'a fait en double précision, correctement, même si quelqu'un a essayé de gâcher la précision en abusant des appels DirectX.

La valeur de Val est déjà erronée au 8ème chiffre significatif. Val est déclaré comme double, et il lui est assigné la valeur double qui a été calculée il y a une microseconde, sans aucun calcul supplémentaire sur le chemin.

Est-ce une version build? Je me demande si C# pourrait avoir omis de stocker la dernière valeur dans Val, la façon dont C++ peut le faire. Que se passe-t-il dans une version de débogage?

+0

J'utilise également DirectX pour la simulation dans mon application. Cela peut-il être la raison? – Rick2047

Questions connexes