2010-08-08 8 views
7

Ich brauche Hilfe für einen seltsamen Fehler zu lösen - wenn ich mod (%) operator auf x86 alle guten, Aber auf x64 bekomme ich manchmal NaN als Rest (es passiert normalerweise mit Angle = 0). Ich habe es geschafft, diesen Fehler außerhalb meines Codes zu reproduzieren, aber nur mit Angle = double.Epsilon (bei meinem Code passiert es auch mit Angle = 0).Mod (%) operator auf x86 vs x64

class Program 
{ 
    public const double M_PI = 3.14159265358979323846; 
    static void Main(string[] args) 
    { 
     double m_2PI = (2 * M_PI); 
     double m_Angle = double.Epsilon; 
     double mod = (m_Angle % m_2PI); 
     //x86 mod = 4.94065645841247E-324 
     //x64 mod = NaN 
     if (double.IsNaN(mod)) 
      Debug.Write(mod); 
    } 
} 

Grüße, Shay

+0

Nicht so sicher, dass es ein Fehler ist - x86 und x64 Gleitkomma können unterschiedliche Ergebnisse zurückgeben. Sie müssen nur das umgehen. –

+1

Kleiner Tipp: Sie können 'Math.PI' anstelle der Angabe als eigene Konstante verwenden –

Antwort

1

Dies ist nicht ein seltsamer Fehler, sondern ein ganz Bug erwartet. Wenn Sie im äußeren Bereich eines numerischen Datentyps sind und mit Operationen spielen, wäre ich überrascht, wenn dies nicht passiert.

Eine Lösung könnte die Mod-Funktion einkapseln.

static double myMod(double v, double m){ 
    if(v < m) return v; 
    return v % m; 
} 

Kann ich fragen, warum machen Sie sich Sorgen über solch einen Grenzfall?

+7

Offensichtlich sind Grenzfälle sehr wichtig. Sie sind für eine große Anzahl von Fehlern in der Produktionssoftware verantwortlich. –

+0

Die angegebene Funktion ist falsch, wenn 'v' oder' m' negativ sein können. – phoog

1

In C# kann der Modulo-Operator mehr als die üblichen Cs int-Werte annehmen. Aber ja, ich denke, es gibt Unterschiede zwischen den ISAs, wenn man epsilon Mengen macht.

In Ihrem Fall das Epsilon in einer ausreichend kleinen Zahl, um die NAN zu verursachen.

Sehen Sie, wenn Sie es mit Schwimmer und anderen Typen reproduzieren können. Wenn Sie sie verwenden könnten, ist das Problem "gelöst".

Als Workaround können Sie die Mathe selbst mit nahe Epsilon tun und nur 0 es in diesem Fall zurückgeben.

0

Haftungsausschluss: Ich bin kein .Net-Programmierer.

Aber das klingt wie ein Fehler. Die Operation ist für die von Ihnen angegebenen Eingänge gut definiert und sollte m_Angle zurückgeben. Meine Vermutung ist, dass die Implementierung unbedingt die Division m_Angle/m_2PI versucht, die für Ihre Eingaben unterläuft. Offensichtlich unterscheidet sich die Handhabung dieser Bedingung zwischen den 32-Bit- und 64-Bit-Plattformen. Dies könnte korrekt durchgeführt worden sein, indem etwas verwendet wird, das der Antwort von Marcus Johansson ähnlich ist, auf Kosten einer leichten Laufzeit-Strafe für die Überprüfung des zusätzlichen Bereichs.

Verwandte Themen