[.NET 2] Math.Pow est buggé !

Introduction

Imaginons que vous souhaitiez obtenir la racine cubique de -0.5.

Vous écrivez dès lors le code suivant : -0.5 ^ (1/3) ou Math.Pow(-0.5, 1/3)

Quelle n'est pas votre suprise d'apprendre que cela fait... NaN ! Pas très pratique quand on sait que cette racine existe pourtant bel et bien !

Pourquoi ce bug ?

En fait, quand vous avez un exposant inférieur à 1, Math.Pow utilise une formule contenant le logarithme. Or le logarithme n'est défini que pour les nombres positifs. Conclusion, pour les nombres négatifs, point de racine cubique.

Comment corriger ce bug ?

Il faut dès lors ruser... Voici ma solution (VB), qui consiste en fonction "v(n, x)"

Public Module MathModule
    Public Function v(ByVal c As Double, ByVal x As Double) As Double
        If x < 0 Then 'Si le nombre est négatif
            v = -((-x) ^ (1 / c)) 'Chercher la racine du nombre positif
            If Math.Round(v ^ c, 3) <> Math.Round(x, 3) Then 
                v = Double.NaN 'Et renvoyer NaN si cette racine ne s'applique pas
            End If
        Else
            v = x ^ (1 / c)
        End If
    End Function
    Public Function v(ByVal x As Double) As Double
        v = x ^ (0.5)
    End Function
End Module
Publié samedi 10 novembre 2007 21:10 par FREMYCOMPANY
Classé sous , ,
Ce post vous a plu ? Ajoutez le dans vos favoris pour ne pas perdre de temps à le retrouver le jour où vous en aurez besoin :

Commentaires

# re: [.NET 2] Math.Pow est buggé ! samedi 10 novembre 2007 21:57

Que ce ne soit pas pratique OK mais dire que c'est buggé quand la règle du jeu est respectée...

Math.Pow(x, y)

Si x &lt; 0 mais pas Moins l'infini:

Valeur de retour = Nan

DIXIT MSDN.

brunews

# re: [.NET 2] Math.Pow est buggé ! samedi 10 novembre 2007 23:17

Selon moi, il s'agit plutôt d'un bug documenté (un peu comme la gestion de certaines dates en OpenXML).

Matou

# re: [.NET 2] Math.Pow est buggé ! dimanche 11 novembre 2007 08:43

Ce n'est pas "buggé", c'est clairement codé comme cela. Cf ici:

http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=94376

et je crois que c'est compatible avec l'API équivalente Java (mais je ne suis pas sûr ;-)

smo

# re: [.NET 2] Math.Pow est buggé ! dimanche 11 novembre 2007 13:08

Oui, je suis d'accord avec toi Matou, pour moi ce n'est rien de plus qu'un "bug" documenté.

Si une fonctione matématique ne renvoie pas la réponse qu'elle est censée fournir, c'est qu'elle est buggée. Que ce soit expliqué dans la MSDN ou pas...

Si la fonction 5-(-5) renvoyait 0, mais que la documentation prévient que la soustraction de nombres de signe opposée renvoie leur addition, vous n'allez pas dire "que ce n'est pas un bug"...

Surtout que

Dim E as Double = -1.1

E ^ (1/3) = -1.1 ^ (1/3) renvoie False... car -1.1 ^ (1/3) est précompilé et renvoie bien la bonne réponse (-1.331).

FREMYCOMPANY

# re: [.NET 2] Math.Pow est buggé ! dimanche 11 novembre 2007 13:36

Rien à voir avec un bug, ni même un bug by design. NaN est la bonne réponse (mathématiquement parlant).

Quand tu calcules 1/3, le résultat en mémoire n'est pas égal à 1/3, c'est normal puisqu'il y a une infinité de 3.

Du coup le résultat de pow n'est pas réel, donc NaN est bien la bonne réponse.

Si tu calcules (-1)^2.00001 tu auras le même problème.

Pour éviter ça tu n'as qu'a toujours calculer la puissance d'un nombre positif (et ajuster le signe à la main).

Morale de l'histoire : renseigne toi avant de crier au loup.

RaptorXP

# re: [.NET 2] Math.Pow est buggé ! dimanche 11 novembre 2007 20:52

Ce que tu dis est faux car si je tape -1.1^(1/3) directement dans le code, j'obtiens bien le résultat attendu ! Et si je fais Pow(1.1, 0.3333333333333331), aussi.

Donc ton argument ne tiens pas

FREMYCOMPANY

# re: [.NET 2] Math.Pow est buggé ! lundi 12 novembre 2007 15:44

Ce n'est pas un "argument", c'est ce qu'on apprend en math.

Si tu ne me crois pas regarde sur Wikipedia :

http://fr.wikipedia.org/wiki/Puissance_(math%C3%A9matiques_%C3%A9l%C3%A9mentaires)

"(Les puissances entières sont en fait des cas particuliers de) la fonction exponentielle :

a^b = exp(b*ln a) définie par tout réel a STRICTEMENT POSITIF"

Si tu veux étendre la définition à a négatif, tu fais appel aux racines n-ièmes de l'unité qui ne sont définies que pour n entier. Donc les seules puissance auxquelles tu *pourrait* étendre cette fonction pour a négatif (mais ce n'est pas la définition d'exponentielle), c'est pour b entier positif et b = (1/3), (1/5)... sinon il n'y a pas de racine réelle pour 0.3, ou 2.1.

Pour tes exemples :

- si tu tapes -1.1^(1/3) ça marche... ben oui, mais si tu tapes (-1.1)^(1/3), en faisant attention a la priorité des opérateur, tu obtiens bien NaN

- si tu fait Pow(1.1, 0.3333333333333331), évidemment que ça marche, le nombre que tu élève est positif.

Non, Math.Pow n'est pas buggée, rassure toi.

RaptorXP


Les 10 derniers blogs postés

- [WPF] Nouvel article sur c2i.fr par Richard Clark le il y a 3 heures et 17 minutes

- F# nouvelle CTP 1.9.6.2 (update) par Pierrick's Blog le il y a 7 heures et 23 minutes

- La suite ...Proposition de collaboration rédactionnelle entre les communautés de développeurs et Microsoft France par LucasR le 09-05-2008, 17:45

- [Fun] Votre simulateur de vol avec Microsoft ESP par Julien Chable le 09-05-2008, 12:02

- [Best Practices] Customisation du My Site : Comment le modifier en amont et en aval par The Mit's Blog le 09-05-2008, 10:47

- Patrick Tisseghem s'en est allé ... par The Mit's Blog le 09-05-2008, 10:04

- MS AutoCollage par alex# le 09-05-2008, 09:18

- Un grand SharePointeur nous a quitte : Patrick Tisseghem manquera à la communauté ! par RedoBlog - The .NET Gentleman !!! le 09-05-2008, 08:52

- [WPF] Comment charger dynamiquement un fichier XAML qui définit des eventhandler ? par Thomas Lebrun le 09-04-2008, 10:56

- Article sur le filtrage des modèles de site SharePoint par The Grib's Lair [Sébastien PICAMELOT - MVP SharePoint] le 09-04-2008, 00:11