2010-08-08 14 views
7

Ho bisogno di aiuto per risolvere uno strano bug - quando uso l'operatore mod (%) su x86 tutto bene, Ma su x64 ottengo a volte NaN come resto (di solito accade con Angolo = 0). Sono riuscito a riprodurre questo bug fuori dal mio codice, ma solo con Angle = double.Epsilon (al mio codice succede anche con Angle = 0).Mod (%) operatore su 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); 
    } 
} 

saluti, Shay

+0

Non sono sicuro che si tratti di un errore - il virgola mobile x86 e x64 può restituire risultati diversi. Potresti aver bisogno di ovviare a questo. –

+1

Piccolo consiglio: è possibile utilizzare 'Math.PI' invece di specificarlo come costante propria –

risposta

1

Questo non è un bug strano, piuttosto un bug molto atteso. Se ti trovi nella fascia esterna di un tipo di dati numerici e giochi con le operazioni, sarei sorpreso se ciò non accadesse.

Una soluzione potrebbe incapsulare la funzione mod.

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

Posso chiederlo, perché ti preoccupi di un caso così borderline?

+7

È chiaro che i casi limite sono molto importanti. Rappresentano un numero enorme di bug nel software di produzione. –

+0

La funzione data non è corretta se 'v' o' m' potrebbe essere negativo. – phoog

1

In C# l'operatore modulo può assumere più dei soliti valori int del C. Ma sì, immagino ci siano delle differenze tra gli ISA quando stai facendo quantità di epsilon.

Nel tuo caso l'epsilon in un numero sufficientemente piccolo da causare il NAN.

Vedere se è possibile riprodurlo con float e altri tipi. Se potessi usarli, il problema è "risolto".

Come soluzione alternativa, è possibile eseguire i calcoli manualmente con epsilon e restituire 0 in questo caso.

0

Disclaimer: Non sono un programmatore .Net.

Ma questo sembra un bug. L'operazione è ben definita per gli input forniti e deve restituire m_Angle. La mia ipotesi è che l'implementazione incondizionatamente tenti la divisione m_Angle/m_2PI, che subisce un underflow per i propri input. Evidentemente, la gestione di questa condizione differisce tra le piattaforme a 32 e 64 bit. Questo potrebbe essere stato fatto correttamente usando qualcosa di simile alla risposta di Marcus Johansson, al costo di una leggera penalità di runtime per il controllo del range extra.

Problemi correlati