public static void Investigations() { double geosyncOrbitR = 42000.0; // Real example, approximate geosynchronous orbit in km double oneMillimeter = 1.0 / 1000.0 / 1000.0; // One mm in kilometers Console.WriteLine("=========== Geosync Orbit plus 1/3 millimeter (and smaller) in kilometers =========="); Console.WriteLine(" Objective is to have fractions of a millimeter correctly accumulate over many additions\n"); double large = geosyncOrbitR; double small = oneMillimeter / 3.0; Console.WriteLine("large: {0}, log10(large): {1:G5}\n", large, Math.Log10(Math.Abs(large))); for (int i = 0; i < 200; i++) { Console.WriteLine("large + small ({0,22:G17}) = {1,22:G17} - sig digits in calc: {2}, log10(small): {3,7:G5}, logs difference: {4,6:G5} ({5}) (CAP V2: {6}, V3: {7})", small, large + small, DecimalAdditionPrecision(large, small), Math.Log10(Math.Abs(small)), Math.Log10(Math.Abs(large)) - Math.Log10(Math.Abs(small)), FloatingPointUtil.AdditionMagnitudeDifference(large, small), FloatingPointUtil.CheckAdditionPrecisionV2(large, small), FloatingPointUtil.CheckAdditionPrecisionV3(large, small)); if (large + small == large) { break; } small *= 0.1; } }
public static void DisplayPrecisionIssue(double a, double b, string whichCalculation, int bodyNumber) { if (debugMessageCount++ < DebugMessageCountLimit) { Debug.WriteLine("Body #{4} {3}: a = {0:G17}, b = {1:G17}, mag diff = {2}", a, b, FloatingPointUtil.AdditionMagnitudeDifference(a, b), whichCalculation, bodyNumber); } if (debugMessageCount == DebugMessageCountLimit) { Debug.WriteLine(">>> Reached limit of {0:N0} precision warning messages. No more will be displayed.", DebugMessageCountLimit); } }