Mon équipe travaille avec un logiciel financier qui expose les valeurs monétaires sous la forme de doubles flottants C#. À l'occasion, nous devons comparer ces valeurs pour voir si elles sont égales à zéro ou tombent sous une limite particulière. Lorsque j'ai remarqué un comportement inattendu dans cette logique, j'ai rapidement découvert les erreurs d'arrondi inhérentes aux doubles flottants (par exemple 1.1 + 2.2 = 3.3000000000000003). Jusqu'à présent, j'ai principalement utilisé les décimales C# pour représenter les valeurs monétaires.Choix d'une valeur Epsilon pour les comparaisons à virgule flottante
Mon équipe a décidé de résoudre ce problème en utilisant l'approche de la valeur epsilon. Essentiellement, lorsque vous comparez deux nombres, si la différence entre ces deux nombres est inférieure à epsilon, ils sont considérés égaux. Nous avons mis en œuvre cette approche de la même manière que décrit dans l'article ci-dessous: https://www.codeproject.com/Articles/383871/Demystify-Csharp-floating-point-equality-and-relat
Notre défi a été de déterminer une valeur appropriée pour epsilon. Nos valeurs monétaires peuvent avoir jusqu'à 3 chiffres à droite de la virgule décimale (échelle = 3). Cela signifie que le plus grand epsilon que nous pourrions utiliser est .0001 (quelque chose de plus grand et le troisième chiffre est ignoré). Puisque les valeurs d'epsilon sont supposées être petites, nous avons décidé de le déplacer d'un point décimal vers .00001 (juste pour être sûr, pourrait-on dire). Les doubles C# ont une précision de at least 15 digits, donc je crois que cette valeur d'epsilon devrait fonctionner si le nombre à gauche du point décimal est inférieur ou égal à 10 chiffres (15 - 5 = 10, où 5 est le nombre de chiffres epsilon est à droite de la virgule décimale). Avec 10 chiffres, nous pouvons représenter des valeurs dans les milliards, jusqu'à 9999999999999. Il est possible que nous ayons des centaines de millions, mais nous ne nous attendons pas à des milliards, donc cette limite devrait suffire.
Est-ce que ma justification pour choisir cette valeur d'epsilon est correcte? J'ai trouvé beaucoup de ressources qui discutent de cette approche, mais je n'ai pas trouvé beaucoup de ressources qui fournissent des conseils sur le choix d'epsilon.
Je pensais que l'utilisation normale, même DP, IEEE754 n'était pas une bonne idée pour les calculs financiers. La sagesse perçue est d'utiliser le type [décimal] de C# (https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/decimal); avez-vous considéré cela? –
@IsaacWoods J'écris un code d'extension pour un logiciel financier sur étagère, donc je n'ai aucun contrôle sur les types de données qu'il utilise. J'ai pensé à convertir les valeurs doubles en décimales, mais si le double contient déjà une erreur d'arrondi, il est simplement copié dans la décimale. –
En raison de certaines expériences douloureuses, en commençant par un gestionnaire me disant "Vous n'aurez plus jamais à lire plus de 200 cartes perforées.", les clauses du formulaire" nous ne nous attendons pas à des milliards "me rendent très nerveux Comment allez-vous imposer la limite? Que se passe-t-il s'il y a une période d'inflation? Vous obtenez une méga banque en tant que client Votre code est utilisé avec une devise différente? –