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 RunTest(long iterations) { Stopwatch stopwatch = new Stopwatch(); long loopTime, randomGenerationTime, additionTime, checkPrecisionTimeV1, checkPrecisionTimeV2, checkPrecisionTimeV3; stopwatch.Start(); for (long i = 0; i < iterations;) { i++; } loopTime = stopwatch.ElapsedMilliseconds; Double[] randomA = new Double[iterations]; Double[] randomB = new Double[iterations]; Random random = new Random(); stopwatch.Reset(); stopwatch.Start(); for (long i = 0; i < iterations; i++) { randomA[i] = random.NextDouble(); randomB[i] = random.NextDouble(); } randomGenerationTime = stopwatch.ElapsedMilliseconds; double sum; stopwatch.Reset(); stopwatch.Start(); for (long i = 0; i < iterations; i++) { sum = randomA[i] + randomB[i]; } additionTime = stopwatch.ElapsedMilliseconds; bool result; stopwatch.Reset(); stopwatch.Start(); for (long i = 0; i < iterations; i++) { result = FloatingPointUtil.CheckAdditionPrecisionV1(randomA[i], randomB[i]); } checkPrecisionTimeV1 = stopwatch.ElapsedMilliseconds; stopwatch.Reset(); stopwatch.Start(); for (long i = 0; i < iterations; i++) { result = FloatingPointUtil.CheckAdditionPrecisionV2(randomA[i], randomB[i]); } checkPrecisionTimeV2 = stopwatch.ElapsedMilliseconds; stopwatch.Reset(); stopwatch.Start(); for (long i = 0; i < iterations; i++) { result = FloatingPointUtil.CheckAdditionPrecisionV3(randomA[i], randomB[i]); } checkPrecisionTimeV3 = stopwatch.ElapsedMilliseconds; Console.WriteLine("Performance Test of CheckAdditionPrecision() - running {0:N0} iterations", iterations); Console.WriteLine("Times in ms:"); Console.WriteLine(" Empty loop: {0:N0}", loopTime); Console.WriteLine(" Random number generation: {0:N0}, net: {1:N0}", randomGenerationTime, randomGenerationTime - loopTime); Console.WriteLine(" Addition: {0:N0}, net: {1:N0}", additionTime, additionTime - loopTime); Console.WriteLine(" CAP V1(): {0:N0}, net: {1:N0}", checkPrecisionTimeV1, checkPrecisionTimeV1 - loopTime); Console.WriteLine(" CAP V2(): {0:N0}, net: {1:N0}", checkPrecisionTimeV2, checkPrecisionTimeV2 - loopTime); Console.WriteLine(" CAP V3(): {0:N0}, net: {1:N0}", checkPrecisionTimeV3, checkPrecisionTimeV3 - loopTime); Console.WriteLine("CheckAdditionPrecisionV3() takes {0:N2} times longer than addition", (checkPrecisionTimeV3 - loopTime) / (additionTime - loopTime)); Console.WriteLine("CheckAdditionPrecisionV3() runs in {0:N2}% time of original version", ((float)(checkPrecisionTimeV3 - loopTime) / (float)(checkPrecisionTimeV1 - loopTime)) * 100.0f); }