math - Angle Normalization C# -
i have angle class has constructor
public angle(int deg, // degrees, minutes, seconds int min, // (signs should agree int sec) // conventional notation.) { /* //bug grade normalization while (deg <= -180) deg += 360; while (deg > math.pi) deg -= 360; //correction end */ double seconds = sec + 60 * (min + 60 * deg); value = seconds * math.pi / 648000.0; normalize(); }
and have these values testing constructor
int[] degrees = { 0, 180, -180, int32.minvalue / 60, 120+180*200000}; int[] minutes = { 0, 0, 0, 0,56}; int[] seconds = { 0, 0, 0, 0,10}; console.writeline("testing constructor angle(int deg, int min)"); (int = 0; < degrees.length; i++) { p = new angle(degrees[i], minutes[i], seconds[i]); console.writeline("p = " + p); } /*testing constructor angle(int deg, int min) p = 0°0'0" p = 180°0'0" p = 180°0'0" p = 0°8'0" wrong output p = -73°11'50" wrong output expected 120 56 10 */
i not understand why there bug here ? , why did utilize split int32.minvalue 60 , 120+180*200000 format ?
the comments in constructor correction code
update: added code of normalize()
// compatibility math libraries , other software // range (-pi,pi] not [0,2pi), enforced next function: void normalize() { double twopi = math.pi + math.pi; while (value <= -math.pi) value += twopi; while (value > math.pi) value -= twopi; }
the problem in piece of code:
double seconds = sec + 60 * (min + 60 * deg);
although storing seconds
double
, conversion int
double
taking place after sec + 60 * (min + 60 * deg)
computed as int
.
the compiler not take double
arithmetics based on type decide store result in. compiler take best operator overload based on types of operands in case int
, valid implicit conversion (in case int
double
) afterwards; hence choosing int
arithmetics , operation overflow in lastly 2 test cases:
int32.minvalue / 60 * 60 * 60
= int32.minvalue * 60
< int32.minvalue
overflow.
120 + 180 * 200000 * 60 * 60
> int32.maxvalue
overflow.
your expected results these 2 cases not considering behavior.
in order solve issue, alter code to:
double seconds = sec + 60 * (min + 60f * deg);
explicitly setting 60
double
typed literal constant (60f
) forcefulness compiler resolve operations double
arithmetics.
also, worth pointing out constructor logic has other issues:
you should validating input data; should valid specify negative minutes or seconds? imo doesn't seem reasonable. deg
should allowed have negative value. should check status , deed accordingly: throw exception (preferable) or normalize sign of min
, sec
based on sign of deg
(ugly , potentially confusing).
your seconds
calculation doesn't seem right negative angles (again, tied previous issue , whatever sign convention have decided implement). unless convention negative angles must have negative deg
, min
, sec
, way computing seconds
wrong because adding minutes , seconds terms no matter sign of deg
.
update there 1 more issue in code missed until had chance test it. of test cases failing because double
doesn't have plenty resolution. think code needs major refactoring; normalize()
should called first. way managing tightly bounded values can not cause overflows or precision loss.
this way it:
public angle(int deg, int min, int sec) { //omitting input values check. double seconds = sec + 60 * (min + 60 * normalize(deg)); value = seconds * math.pi / 648000f; } private int normalize(int deg) { int normalizeddeg = deg % 360; if (normalizeddeg <= -180) normalizeddeg += 360; else if (normalizeddeg > 180) normalizeddeg -= 360; homecoming normalizeddeg; }
c# math angle pi
No comments:
Post a Comment