10
votes

Math.cos & math.sin in c #

J'essaie quelque chose que je pensais être raisonnablement simple. J'ai un angle, une position et une distance et je veux trouver le x, y coordonnated à partir de ces informations.

Avec un exemple d'entrée de 90 degrés, je convertis la valeur en radians avec le code suivant: P >

Math.Cos(radians)


6 commentaires

C'est définitivement des rondes à 0. Utilisez un spécificateur de format lorsque vous convertissez la valeur en une chaîne afin que l'utilisateur le voit la façon dont ils attendent.


OK, je prends le point que le manque de précision est dû au manque de précision dans les types de points flottants, mais comment quelque chose comme la calculatrice de Windows parvient-il à obtenir la réponse morte sur, triche-t-il et utilise une table de recherche?


@Elaverick - qui dit que la calculatrice Windows utilise .NET double (ce n'est pas) ou un type de point flottant (ce n'est pas). Et qui dit que cela émet des résultats précis d'un calcul plutôt que d'appliquer des règles d'arrondi sans faune?


La calculatrice était Complètement réécrit il y a quelques années utiliser des arithmétiques arbitraires-précision en réponse à précisément de ces bugs.


Grâce à tous ceux qui ont offert des réponses à cela, vous présentez la visualisation pour que les données étaient fausses, donc j'avais supposé que cela doit être dû au niveau de précision offert par les mathématiques. Je suppose que ça va m'apprendre à lire la production plutôt que de faire des hypothèses sur ce que cela dit.


Votre valeur de PI est désactivée par quelques parties de 10 à la 17. Cela ne devrait donc pas être une surprise que le résultat est également désactivé par quelques parties de 10 à 17. Pi est arrondi à 16 chiffres environ.


7 Réponses :


13
votes

Permettez-moi de répondre à votre question avec un autre: quelle distance pensez-vous que 6.12303176911189e-17 est de 0? Ce que vous appelez déviance est en fait du fait que les numéros de points flottants sont stockés en interne. Je vous recommanderais de lire le ARTICLE . En .net, ils sont stockés à l'aide du IEEE 754 Standard .


1 commentaires

Appliquer une trigonométrie de base, la distance entre deux particules qui parcourent une année légère avec cette erreur d'angle est de 6,1e-17 * 9.4e15 ~ = 0,57 = 57cm. Je ne pense pas que cela mérite de trop vous inquiéter non plus.



2
votes

Lire sur arithmétique de point flottant . Ce n'est jamais et ne peut jamais être exact. Ne comparez jamais exactement à rien, mais vérifiez si les chiffres diffèrent par un (petit) epsilon.


3 commentaires

C'est parfois exact. Juste pas tout le temps.


C'est précisément aussi exact que autre chose dans un ordinateur qui n'utilise pas le hasard. Le problème est la fixation générale de la plupart des personnes (y compris des programmeurs informatiques) avec des représentations décimales.


@Damien_the_unbeliever complètement et totalement faux. C'est inexact car l'ensemble de chiffres réels ne peut pas être représenté avec précision grâce à aucun moyen physique ; Cela n'a rien à voir avec la base de numéro. Les autres choses dans un ordinateur peuvent être représentées exactement ... des nombres entiers et rationnels, par exemple. Même le problème ici peut être exprimé exactement par une représentation symbolique plutôt que numérique, mais cela ne peut que vous prendre jusqu'à présent.



6
votes

voir les réponses ci-dessus. N'oubliez pas que le 6.12303176911189E-17 est 0.00000000000000006 (j'ai peut-être même manqué un zéro là-bas!) C'est donc une écart très très faible.


0 commentaires

1
votes

Étant donné que le calcul du calcul est vraiment proche de 0 (zéro), vous pouvez simplement utiliser l'arrondi: xxx

donc, Calcul du péché / cos du radian :: xxx

lequel si yourradianvalue = 90 , renvoie sin = 1 et cos = 0 .


0 commentaires

2
votes

Les autres postes sont corrects sur la question pratique de travailler avec des implémentations de points flottants qui renvoient des résultats avec de petites erreurs. Cependant, ce serait bien si les implémentations de la bibliothèque de points flottants préservent l'identité de base des fonctions bien connues:

math.sin (math.pi) devrait égal 0 ,
math.cos (math.pi) devrait égal -1
math.sin (math.pi / 2) devrait égal 1 ,
math.cos (math.pi / 2) devrait égal 0 , etc.

Vous vous attendez à ce qu'une bibliothèque ponctuelle flottante respecte ces autres identités trigonométriques , quoi que ce soit les erreurs mineures dans ses valeurs constantes (par exemple, MATH.PI).

Le fait que vous obteniez une petite erreur de math.cos (math.pi / 2) indique que la mise en œuvre est en train de calculer le résultat, plutôt que de la tirer d'une table. Une meilleure implémentation de math.cos et les autres fonctions transcendantaux pourrait être plus précise pour des identités spécifiques.

Je suis sûr que dans le cas de C #, ce comportement est attendu, et Microsoft ne pouvait donc pas le changer sans affecter le code existant. Si vous obtenez le résultat précis de l'identité trigonométrique spécifique, vous pouvez envelopper les fonctions de point flottant natives avec un code qui vérifie les entrées connues.


0 commentaires

4
votes

Vous devez utiliser l'arrondi

var radians = Math.PI * degres / 180.0;
var cos = Math.Round(Math.Cos(radians), 2);
var sin = Math.Round(Math.Sin(radians), 2);


0 commentaires

0
votes

Comme remarqué par @ B1TW153, ce serait génial si les valeurs exactes étaient renvoyées pour les multiples de PI / 2. Et c'est exactement ce que Microsoft a fait dans leur System.numerics Bibliothèque; Si vous examinez le code source de matrix3x2.creailotation , vous remarquerez qu'ils gérerent N * PI / 2 cas manuellement: https://github.com/microsoft/referencesource/blob/master/system.numeric/system/numerics/matrix3x2. CS # L325


0 commentaires