Mod (%) operator on x86 vs x64
I need help for resolve a strange bug – when I use mod (%) operator on x86 all good , But on x64 I get sometimes NaN as remainder ( it usually happens with Angle = 0). I managed to reproduce that bug outside my code , but only with Angle = double.Epsilon (at my code it also happens with Angle = 0).
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);
}
}
Regards , Shay
This is not a strange bug, rather a quite expected bug. If you are in the outer range of a numerical datatype and play with operations, I would be surprised if this doesn't happen.
A solution might be encapsulating the mod function.
static double myMod(double v, double m){
if(v < m) return v;
return v % m;
}
Can i ask, why do you worry about such a borderline case?
In C# the modulus operator can take more than the usual C's int values. But yeah, I guess there are differences between ISA's when you are doing epsilon quantities.
In your case the epsilon in a sufficiently small number to cause the NAN.
See if you can reproduce it with float and other types. If you could use them, the problem is "solved".
As a workaround you can do the math yourself with near epsilon and just return 0 it that case.
Disclaimer: I'm not a .Net programmer.
But this sounds like a bug. The operation is well defined for the inputs you supplied, and should return m_Angle
. My guess is that the implementation unconditionally attempts the division m_Angle/m_2PI
, which underflows for your inputs. Evidently, the handling of this condition differs between the 32-bit and 64-bit platforms. This could have been done correctly using something similar to Marcus Johansson's answer, at the cost of a slight
runtime penalty for the extra range checking.
精彩评论