Task: Arithmetic-geometric mean



C#: namespace RosettaCode.ArithmeticGeometricMean
{
    using System;
    using System.Collections.Generic;
    using System.Globalization;

    internal static class Program
    {
        private static double ArithmeticGeometricMean(double number,
                                                      double otherNumber,
                                                      IEqualityComparer<double>
                                                          comparer)
        {
            return comparer.Equals(number, otherNumber)
                       ? number
                       : ArithmeticGeometricMean(
                           ArithmeticMean(number, otherNumber),
                           GeometricMean(number, otherNumber), comparer);
        }

        private static double ArithmeticMean(double number, double otherNumber)
        {
            return 0.5 * (number + otherNumber);
        }

        private static double GeometricMean(double number, double otherNumber)
        {
            return Math.Sqrt(number * otherNumber);
        }

        private static void Main()
        {
            Console.WriteLine(
                ArithmeticGeometricMean(1, 0.5 * Math.Sqrt(2),
                                        new RelativeDifferenceComparer(1e-5)).
                    ToString(CultureInfo.InvariantCulture));
        }

        private class RelativeDifferenceComparer : IEqualityComparer<double>
        {
            private readonly double _maximumRelativeDifference;

            internal RelativeDifferenceComparer(double maximumRelativeDifference)
            {
                _maximumRelativeDifference = maximumRelativeDifference;
            }

            public bool Equals(double number, double otherNumber)
            {
                return RelativeDifference(number, otherNumber) <=
                       _maximumRelativeDifference;
            }

            public int GetHashCode(double number)
            {
                return number.GetHashCode();
            }

            private static double RelativeDifference(double number,
                                                     double otherNumber)
            {
                return AbsoluteDifference(number, otherNumber) /
                       Norm(number, otherNumber);
            }

            private static double AbsoluteDifference(double number,
                                                     double otherNumber)
            {
                return Math.Abs(number - otherNumber);
            }

            private static double Norm(double number, double otherNumber)
            {
                return 0.5 * (Math.Abs(number) + Math.Abs(otherNumber));
            }
        }
    }
}







COBOL: IDENTIFICATION DIVISION.
PROGRAM-ID. ARITHMETIC-GEOMETRIC-MEAN-PROG.
DATA DIVISION.
WORKING-STORAGE SECTION.
01  AGM-VARS.
    05 A       PIC 9V9(16).
    05 A-ZERO  PIC 9V9(16).
    05 G       PIC 9V9(16).
    05 DIFF    PIC 9V9(16) VALUE 1.
* Initialize DIFF with a non-zero value, otherwise AGM-PARAGRAPH
* is never performed at all.
PROCEDURE DIVISION.
TEST-PARAGRAPH.
    MOVE    1 TO A.
    COMPUTE G = 1 / FUNCTION SQRT(2).
* The program will run with the test values. If you would rather
* calculate the AGM of numbers input at the console, comment out
* TEST-PARAGRAPH and un-comment-out INPUT-A-AND-G-PARAGRAPH.
* INPUT-A-AND-G-PARAGRAPH.
*     DISPLAY 'Enter two numbers.'
*     ACCEPT  A.
*     ACCEPT  G.
CONTROL-PARAGRAPH.
    PERFORM AGM-PARAGRAPH UNTIL DIFF IS LESS THAN 0.000000000000001.
    DISPLAY A.
    STOP RUN.
AGM-PARAGRAPH.
    MOVE     A TO A-ZERO.
    COMPUTE  A = (A-ZERO + G) / 2.
    MULTIPLY A-ZERO BY G GIVING G.
    COMPUTE  G = FUNCTION SQRT(G).
    SUBTRACT A FROM G GIVING DIFF.
    COMPUTE  DIFF = FUNCTION ABS(DIFF).