Tuesday, 15 March 2011

math - Angle Normalization C# -



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