

 This page uses content from Wikipedia. The original article was at Arithmetic-geometric mean. The list of authors can be seen in the page history. As with Rosetta Code, the text of Wikipedia is available under the GNU FDL. (See links for details on variance)



Task

Write a function to compute the arithmetic-geometric mean of two numbers.



The arithmetic-geometric mean of two numbers can be (usefully) denoted as 




a
g
m

(
a
,
g
)


{\displaystyle \mathrm {agm} (a,g)}

, and is equal to the limit of the sequence:

 




a

0


=
a
;


g

0


=
g


{\displaystyle a_{0}=a;\qquad g_{0}=g}


 




a

n
+
1


=



1
2



(

a

n


+

g

n


)
;


g

n
+
1


=



a

n



g

n




.


{\displaystyle a_{n+1}={\tfrac {1}{2}}(a_{n}+g_{n});\quad g_{n+1}={\sqrt {a_{n}g_{n}}}.}


Since the limit of 




a

n


−

g

n




{\displaystyle a_{n}-g_{n}}

 tends (rapidly) to zero with iterations, this is an efficient method.

Demonstrate the function by calculating:






a
g
m

(
1
,
1

/



2


)


{\displaystyle \mathrm {agm} (1,1/{\sqrt {2}})}




Also see

   mathworld.wolfram.com/Arithmetic-Geometric Mean


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));
            }
        }
    }
}