
| This page uses content fromWikipedia. The original article was atArithmetic-geometric mean. The list of authors can be seen in thepage history.As with Rosetta Code, the text of Wikipediais available under theGNU FDL. (See links for details on variance) |
Write a function to compute thearithmetic-geometric mean of two numbers.
The arithmetic-geometric mean of two numbers can be (usefully) denoted as, and is equal to the limit of the sequence:
Since the limit of tends (rapidly) to zero with iterations, this is an efficient method.
Demonstrate the function by calculating:
F agm(a0, g0, tolerance = 1e-10) V an = (a0 + g0) / 2.0 V gn = sqrt(a0 * g0) L abs(an - gn) > tolerance (an, gn) = ((an + gn) / 2.0, sqrt(an * gn)) R an print(agm(1, 1 / sqrt(2)))
0.847213
For maximum compatibility, this program uses only the basic instruction set.
AGM CSECT USING AGM,R13SAVEAREA B STM-SAVEAREA(R15) DC 17F'0' DC CL8'AGM'STM STM R14,R12,12(R13) ST R13,4(R15) ST R15,8(R13) LR R13,R15 ZAP A,K a=1 ZAP PWL8,K MP PWL8,K DP PWL8,=P'2' ZAP PWL8,PWL8(7) BAL R14,SQRT ZAP G,PWL8 g=sqrt(1/2)WHILE1 EQU * while a!=g ZAP PWL8,A SP PWL8,G CP PWL8,=P'0' (a-g)!=0 BE EWHILE1 ZAP PWL8,A AP PWL8,G DP PWL8,=P'2' ZAP AN,PWL8(7) an=(a+g)/2 ZAP PWL8,A MP PWL8,G BAL R14,SQRT ZAP G,PWL8 g=sqrt(a*g) ZAP A,AN a=an B WHILE1EWHILE1 EQU * ZAP PWL8,A UNPK ZWL16,PWL8 MVC CWL16,ZWL16 OI CWL16+15,X'F0' MVI CWL16,C'+' CP PWL8,=P'0' BNM *+8 MVI CWL16,C'-' MVC CWL80+0(15),CWL16 MVC CWL80+9(1),=C'.' /k (15-6=9) XPRNT CWL80,80 display a L R13,4(0,R13) LM R14,R12,12(R13) XR R15,R15 BR R14 DS 0FK DC PL8'1000000' 10^6 A DS PL8G DS PL8AN DS PL8* ****** SQRT *******************SQRT CNOP 0,4 function sqrt(x) ZAP X,PWL8 ZAP X0,=P'0' x0=0 ZAP X1,=P'1' x1=1WHILE2 EQU * while x0!=x1 ZAP PWL8,X0 SP PWL8,X1 CP PWL8,=P'0' (x0-x1)!=0 BE EWHILE2 ZAP X0,X1 x0=x1 ZAP PWL16,X DP PWL16,X1 ZAP XW,PWL16(8) xw=x/x1 ZAP PWL8,X1 AP PWL8,XW DP PWL8,=P'2' ZAP PWL8,PWL8(7) ZAP X2,PWL8 x2=(x1+xw)/2 ZAP X1,X2 x1=x2 B WHILE2EWHILE2 EQU * ZAP PWL8,X1 return x1 BR R14 DS 0FX DS PL8X0 DS PL8X1 DS PL8X2 DS PL8XW DS PL8* end SQRTPWL8 DC PL8'0'PWL16 DC PL16'0'CWL80 DC CL80' 'CWL16 DS CL16ZWL16 DS ZL16 LTORG YREGS END AGM
+00000000.84721
: epsilon 1.0e-12 ;with: n: iter \ n1 n2 -- n1 n2 2dup * sqrt >r + 2 / r> ;: agn \ n1 n2 -- n repeat iter 2dup epsilon ~= not while! drop ;"agn(1, 1/sqrt(2)) = " . 1 1 2 sqrt / agn "%.10f" s:strfmt . cr;withbye
agn(1, 1/sqrt(2)) = 0.8472130848
INCLUDE "H6:REALMATH.ACT"PROC Agm(REAL POINTER a0,g0,result) REAL a,g,prevA,tmp,r2 RealAssign(a0,a) RealAssign(g0,g) IntToReal(2,r2) DO RealAssign(a,prevA) RealAdd(a,g,tmp) RealDiv(tmp,r2,a) RealMult(prevA,g,tmp) Sqrt(tmp,g) IF RealGreaterOrEqual(a,prevA) THEN EXIT FI OD RealAssign(a,result)RETURNPROC Main() REAL r1,r2,tmp,g,res Put(125) PutE() ;clear screen MathInit() IntToReal(1,r1) IntToReal(2,r2) Sqrt(r2,tmp) RealDiv(r1,tmp,g) Agm(r1,g,res) Print("agm(") PrintR(r1) Print(",") PrintR(g) Print(")=") PrintRE(res)RETURNScreenshot from Atari 8-bit computer
agm(1,.7071067873)=.847213085
withAda.Text_IO,Ada.Numerics.Generic_Elementary_Functions;procedureArith_Geom_MeanistypeNumisdigits18;-- the largest value gnat/gcc allowspackageN_IOis newAda.Text_IO.Float_IO(Num);packageMathis newAda.Numerics.Generic_Elementary_Functions(Num);functionAGM(A,G:Num)returnNumisOld_G:Num;New_G:Num:=G;New_A:Num:=A;beginloopOld_G:=New_G;New_G:=Math.Sqrt(New_A*New_G);New_A:=(Old_G+New_A)*0.5;exitwhen(New_A-New_G)<=Num'Epsilon;-- Num'Epsilon denotes the relative error when performing arithmetic over Numendloop;returnNew_G;endAGM;beginN_IO.Put(AGM(1.0,1.0/Math.Sqrt(2.0)),Fore=>1,Aft=>17,Exp=>0);endArith_Geom_Mean;
Output:
0.84721308479397909
ALGOL 68 Genie gives IEEE double precision for REAL quantities, 28 decimal digits for LONG REALs and, by default, 63 decimal digits for LONG LONG REAL though this can be made arbitrarily greater with a pragmatic comment.
Note that the sizes of REAL, LONG REAL and LONG LONG REAL may vary depending on the platform and ALGOL 68 Genie version - the output shown here is for version 2 under Windows/Linux.
Printing out the difference between the means at each iteration nicely demonstrates the quadratic convergence.
BEGIN PROC agm = (LONG REAL x, y) LONG REAL : BEGIN IF x < LONG 0.0 OR y < LONG 0.0 THEN -LONG 1.0 ELIF x + y = LONG 0.0 THEN LONG 0.0CO Edge cases CO ELSE LONG REAL a := x, g := y; LONG REAL epsilon := a + g; LONG REAL next a := (a + g) / LONG 2.0, next g := long sqrt (a * g); LONG REAL next epsilon := ABS (a - g); WHILE next epsilon < epsilon DO print ((epsilon, " ", next epsilon, newline)); epsilon := next epsilon; a := next a; g := next g; next a := (a + g) / LONG 2.0; next g := long sqrt (a * g); next epsilon := ABS (a - g) OD; a FI END; printf (($lg(-35,33)l$, agm (LONG 1.0, LONG 1.0 / long sqrt (LONG 2.0))))END
+1.707106781186547524400844362e +0 +2.928932188134524755991556379e -1+2.928932188134524755991556379e -1 +1.265697533955921916929670477e -2+1.265697533955921916929670477e -2 +2.363617660269221214237489508e -5+2.363617660269221214237489508e -5 +8.242743980540458935740117000e -11+8.242743980540458935740117000e -11 +1.002445937606580000000000000e -21+1.002445937606580000000000000e -21 +4.595001000000000000000000000e -29+4.595001000000000000000000000e -29 +4.595000000000000000000000000e -290.847213084793979086606499123550000
agd←{(⍺-⍵)<10*¯8:⍺⋄((⍺+⍵)÷2)∇(⍺×⍵)*÷2}1agd÷2*÷2
Output:
0.8472130848
By functional composition:
-- ARITHMETIC GEOMETRIC MEAN -------------------------------------------------propertytolerance:1.0E-5-- agm :: Num a => a -> a -> aonagm(a,g)scriptwithinToleranceon|λ|(m)tellmto((itsan)-(itsgn))<toleranceend|λ|endscriptscriptnextRefinementon|λ|(m)tellmset{an,gn}to{itsan,itsgn}{an:(an+gn)/2,gn:(an*gn)^0.5}endtellend|λ|endscriptanof|until|(withinTolerance,¬nextRefinement,{an:(a+g)/2,gn:(a*g)^0.5})endagm-- TEST ----------------------------------------------------------------------onrunagm(1,1/(2^0.5))--> 0.847213084835endrun-- GENERIC FUNCTIONS ----------------------------------------------------------- until :: (a -> Bool) -> (a -> a) -> a -> aon|until|(p,f,x)setmptomReturn(p)setvtoxtellmReturn(f)repeatuntilmp's|λ|(v)setvto|λ|(v)endrepeatendtellreturnvend|until|-- Lift 2nd class handler function into 1st class script wrapper-- mReturn :: Handler -> ScriptonmReturn(f)ifclassoffisscriptthenfelsescriptproperty|λ|:fendscriptendifendmReturn
0.847213084835
agm:function[a,g][delta:1e-15[aNew,aOld,gOld]: @[0, a, g]while[delta<absaOld-gOld][aNew:0.5*aOld+gOldgOld:sqrtaOld*gOldaOld:aNew]returnaOld]printagm1.01.0/sqrt2.0
0.8472130847939792
agm(a,g,tolerance=1.0e-15){Whileabs(a-g)>tolerance{an:=.5*(a+g)g:=sqrt(a*g)a:=an}returna}SetFormat,FloatFast,0.15MsgBox%agm(1,1/sqrt(2))
Output:
0.847213084793979
#!/usr/bin/awk -fBEGIN{printf"%.16g\n",agm(1.0,sqrt(0.5))}functionagm(a,g){while(1){a0=aa=(a0+g)/2g=sqrt(a0*g)if(abs(a0-a)<abs(a)*1e-15)break}returna}functionabs(x){return(x<0?-x:x)}
Output
0.8472130847939792
100PROGRAMArithmeticGeometricMean110FUNCTIONAGM(A,G)120DO130LETTA=(A+G)/2140LETG=SQR(A*G)150LETTmp=A160LETA=TA170LETTA=Tmp180LOOPUNTILA=TA190LETAGM=A200ENDFUNCTION210REM ********************220PRINTAGM(1,1/SQR(2))230END
.84721308479398
Same code asCommodore BASICTheBASIC solution works without any changes.
print AGM(1, 1 / sqr(2))endfunction AGM(a, g)Dota = (a + g) / 2g = sqr(a * g)x = aa = tata = xuntil a = tareturn aend function
0.84721308479
*FLOAT64@%=&1010PRINTFNagm(1,1/SQR(2))ENDDEFFNagm(a,g)LOCALtaREPEATta=aa=(a+g)/2g=SQR(ta*g)UNTILa=ta=a
0.8472130847939792
10printagm(1,1/sqr(2))20end100subagm(a,g)110do120letta=(a+g)/2130letg=sqr(a*g)140letx=a150leta=ta160letta=x170loopuntila=ta180agm=a190endsub
0.847213
10 A = 120 G = 1/SQR(2)30 GOSUB 10040 PRINT A50 END100 TA = A110 A = (A+G)/2120 G = SQR(TA*G)130 IF A<TA THEN 100140 RETURN
leta=1letg=1/sqrt(2)dolett=(a+g)/2letg=sqrt(a*g)letx=aleta=tlett=xloopuntila=tprinta
0.85
' version 16-09-2015' compile with: fbc -s consoleFunctionagm(aAsDouble,gAsDouble)AsDoubleDimAsDoublet_aDot_a=(a+g)/2g=Sqr(a*g)Swapa,t_aLoopUntila=t_aReturnaEndFunction' ------=< MAIN >=------Printagm(1,1/Sqr(2))' empty keyboard bufferWhileInKey<>"":WendPrint:Print"hit any key to end program"SleepEnd
0.8472130847939792
PublicSubMain()PrintAGM(1,1/Sqr(2))EndFunctionAGM(aAsFloat,gAsFloat)AsFloatDimt_aAsFloatDot_a=(a+g)/2g=Sqr(a*g)Swapa,t_aLoopUntila=t_aReturnaEndFunction
10A=120G=1!/SQR(2!)30FORI=1TO20'twenty iterations is plenty40B=(A+G)/250G=SQR(A*G)60A=B70NEXTI80PRINTA
100 PRINT AGM(1,1/SQR(2))110 DEF AGM(A,G)120 DO130 LET TA=A140 LET A=(A+G)/2:LET G=SQR(TA*G)150 LOOP UNTIL A=TA160 LET AGM=A170 END DEF
print agm(1, 1/sqr(2))print using("#.#################",agm(1, 1/sqr(2)))endfunction agm(a,g) do absdiff = abs(a-g) an=(a+g)/2 gn=sqr(a*g) a=an g=gn loop while abs(an-gn)< absdiff agm = aend function0.847213080.84721308479397904
10LETA=120LETG=1/SQR(2)30GOSUB6040PRINTA50STOP60LETT=A70LETA=(A+G)/280LETG=SQR(T*G)90IFA<TTHEN60100RETURN110END
.84721308
TheCommodore BASIC solution works without any changes.
TheGW-BASIC solution works without any changes.
Procedure.dAGM(a.d,g.d,ErrLim.d=1e-15)Protected.dta=a+1,tgWhileta<>ata=a:tg=ga=(ta+tg)*0.5g=Sqr(ta*tg)WendProcedureReturnaEndProcedureIfOpenConsole()PrintN(StrD(AGM(1,1/Sqr(2)),16))Input()CloseConsole()EndIf
0.8472130847939792
PRINTAGM(1,1/SQR(2))ENDFUNCTIONAGM(a,g)DOta=(a+g)/2g=SQR(a*g)SWAPa,taLOOPUNTILa=taAGM=aENDFUNCTION
.8472131
10LETA=120LETG=1/SQR(2)30GOSUB10040PRINTA50END100LETT=A110LETA=(A+G)/2120LETG=SQR(T*G)130IFA<TTHEN100140RETURN
0.8472130847939792
print agm(1, 1/sqr(2))print agm(1,1/2^.5)print using("#.############################",agm(1, 1/sqr(2)))function agm(agm,g) while agm an = (agm + g)/2 gn = sqr(agm*g) if abs(agm-g) <= abs(an-gn) then exit while agm = an g = gn wendend function0.8472130850.8472130850.8472130847939791165772005376
Works with 1k of RAM.
The specification calls for a function. Sadly that is not available to us, so this program uses a subroutine: pass the arguments in the global variablesA andG, and the result will be returned inAGM. The performance is quite acceptable. Note that the subroutine clobbersA andG, so you should save them if you want to use them again.
Better precision than this is not easily obtainable on the ZX81, unfortunately.
10LETA=120LETG=1/SQR230GOSUB10040PRINTAGM50STOP100LETA0=A110LETA=(A+G)/2120LETG=SQR(A0*G)130IFABS(A-G)>.00000001THENGOTO100140LETAGM=A150RETURN
0.84721309
1→A:1/sqrt(2)→GWhile abs(A-G)>e-15(A+G)/2→Bsqrt(AG)→G:B→AEndA
.8472130848
FUNCTIONAGM(a,g)DOLETta=(a+g)/2LETg=SQR(a*g)LETx=aLETa=taLETta=xLOOPUNTILa=taLETAGM=aENDFUNCTIONPRINTAGM(1,1/SQR(2))END
.84721308
PrivateFunctionagm(aAsDouble,gAsDouble,OptionaltoleranceAsDouble=0.000000000000001)AsDoubleDoWhileAbs(a-g)>tolerancetmp=aa=(a+g)/2g=Sqr(tmp*g)Debug.PrintaLoopagm=aEndFunctionPublicSubmain()Debug.Printagm(1,1/Sqr(2))EndSub
0,853553390593274 0,847224902923494 0,847213084835193 0,847213084793979 0,847213084793979
Functionagm(a,g)DoUntila=tmp_atmp_a=aa=(a+g)/2g=Sqr(tmp_a*g)Loopagm=aEndFunctionWScript.Echoagm(1,1/Sqr(2))
0.847213084793979
printAGM(1,1/sqrt(2))endsubAGM(a,g)repeatta=(a+g)/2g=sqrt(a*g)x=aa=tata=xuntila=tareturnaendsub
0.847213
ImportsSystem.MathImportsSystem.ConsoleModuleModule1FunctionCalcAGM(ByValaAsDouble,ByValbAsDouble)AsDoubleDimcAsDouble,dAsDouble=0,ldAsDouble=1Whileld<>d:c=a:a=(a+b)/2:b=Sqrt(c*b)ld=d:d=a-b:EndWhile:ReturnbEndFunctionFunctionDecSqRoot(ByValvAsDecimal)AsDecimalDimrAsDecimal=CDec(Sqrt(CDbl(v))),tAsDecimal=0,dAsDecimal=0,ldAsDecimal=1Whileld<>d:t=v/r:r=(r+t)/2ld=d:d=t-r:EndWhile:ReturntEndFunctionFunctionCalcAGM(ByValaAsDecimal,ByValbAsDecimal)AsDecimalDimcAsDecimal,dAsDecimal=0,ldAsDecimal=1Whileld<>d:c=a:a=(a+b)/2:b=DecSqRoot(c*b)ld=d:d=a-b:EndWhile:ReturnbEndFunctionSubMain(ByValargsAsString())WriteLine("Double result: {0}",CalcAGM(1.0,DecSqRoot(0.5)))WriteLine("Decimal result: {0}",CalcAGM(1D,DecSqRoot(0.5D)))IfSystem.Diagnostics.Debugger.IsAttachedThenReadKey()EndSubEndModule
Double result: 0.847213084793979Decimal result: 0.8472130847939790866064991235
ImportsSystem.MathImportsSystem.ConsoleImportsBI=System.Numerics.BigIntegerModuleModule1FunctionBIP(ByValleadDigAsChar,ByValnumDigsAsInteger)AsBIBIP=BI.Parse(leadDig&NewString("0"c,numDigs))EndFunctionFunctionIntSqRoot(ByValvAsBI,ByValresAsBI)AsBI' res is the initial guess of the square rootDimdAsBI=0,dlAsBI=1Whiledl<>d:IntSqRoot=v/res:res=(res+IntSqRoot)/2dl=d:d=IntSqRoot-res:EndWhileEndFunctionFunctionCalcByAGM(ByValdigitsAsInteger)AsBIDimaAsBI=BIP("1"c,digits),' value is 1, extended to required number of digitscasBI,' a temporary variable for swapping a and bdiffAsBI=0,ldiffAsBI=1' difference of a and b, last differenceCalcByAGM=BI.Parse(String.Format("{0:0.00000000000000000}",' initial value of square root of 0.5Sqrt(0.5)).Substring(2)&NewString("0"c,digits-17))CalcByAGM=IntSqRoot(BIP("5"c,(digits<<1)-1),CalcByAGM)' value is now the square root of 0.5Whileldiff<>diff:c=a:a=(a+CalcByAGM)>>1:CalcByAGM=IntSqRoot(c*CalcByAGM,a)ldiff=diff:diff=a-CalcByAGM:EndWhileEndFunctionSubMain(ByValargsAsString())DimdigitsAsInteger=25000Ifargs.Length>0ThenInteger.TryParse(args(0),digits):_Ifdigits<1OrElsedigits>999999Thendigits=25000WriteLine("0.{0}",CalcByAGM(digits))IfSystem.Diagnostics.Debugger.IsAttachedThenReadKey()EndSubEndModule
0.8472130847939790866064991234821916364814459103269421850605793726597340048341347597232002939946112299421222856252334109630979626658308710596997136359833842511763268142890603897067686016166500482811887218977133094117674620199443929629021672891944995072316778973468639476066710579805578521731403493983042004221192160398395535950981936412937163406460295999679705994343516020318426487569502421748638554059819545816017424178878541927588041627190120855876856483268341404312184008040358092045594943138778151209265222545743971242868207663409547336745996217926655353486256861185433086262872872875630108355631935706687147856390889821151088363521476969796126218329432284178681137684451700181460219136940270209459966835135963278808042743454817445873632200251539529362658066141983656164916262596074347237066169023530800173753128478525584306319074542749341526857906552694060031475910203327467196861247963255105546489028208552974396512499400966255286606758044873538921857014011677169765350140849524768489932573213370289846689391946658618737529663875622660459147770442046810892565844083803204091061900315370673411959410100747433105990550582052432600995169279241747821697678106168369771411073927334392155014302200708736736596227214925877619285105238036702689046390962190766364423553808590294523406519001334234510583834171218051425500392370111132541114461262890625413355052664365359582455215629339751825147065013464104705697935568130660632937334503871097709729487591717901581732028157828848714993134081549334236779704471278593761859508514667736455467920161593422399714298407078888227903265675159652843581779572728480835648996350440414073422611018338354697596266333042208499985230074270393027724347497971797326455254654301983169496846109869074390506801376611925291977093844129970701588949316666116199459226501131118396635250253056164643158720845452298877547517727274765672164898291823923889520720764283971088470596035692199292183190154814128076659269829446445714923966632997307581390495762243896242317520950731901842446244237098642728114951118082282605386248461767518014098312749725765198375649235690280021617490553142720815343954059556357637112728165705973733744297003905604015638866307222570038923015911237696012158008177907786335124086243107357158376592650454665278733787444483440631024475703968125545398226643035341641303561380163416557526558975294452116687345122019122746673319157124076375382110696814107692639007483317574339675231966033086497357138387419609898383220288269488219130281936694995442224069727616862136951165783888501219909616065545461154325314816424933269479700415949147632311292059351651899794335004597628821729262591808940550843146639378254833513955019065337087206206402407705607584879649984365159272826453442863661541914258577710675618501727803328717519518930503180550524542602233552290077141812879865435118791800635627959362476826778641224946033812608262825409889531252767753465624327921451122955551603181843313369296172304178385515712556740498341666592696958000895372457305769454227537216020968719147039887846636724326270619112707171659082464004167994112040565710364083000241929439855307399465653967781049270105541035951333943219992506667620207839469555376055179640100974921885631130101781388857879381317209594806253920130098365028791769582798590527994772194179799702494306215841946888532811549772157996019440962347768614408507573928429882375939682322367058033413477462311289762585932437663177897491107726190970448952220450963072551559009382490402136480779203476721504856844602255440999282616317431264228578762898338065072202301037175314926350463106018857377256700661838129058063895450812703131137104371613583348806583395543121790134839883321641305763524471251153947206667033010134871651632411382881763983962952612114126321979596509865678675525076076042409590751752302194610453256433324961490125353332922372386894812788502013596630537605584935892839163046940388785496002747148719780145765957904958580226006609952496736432496683346176010660815670697514238186650361083885220976165500251607311499216129477579019972924868963822060380876027628167237016681910663358577515465038133423672234764202655856558846416010210540489855618711473588497637840648642679818650448631907747038228671143515112300360708657429886477146674733750114345818852797006056211724692174847180694866251199472893444270378304620707354938052872720621560630718828685805645211106967080285699069825769177220998671959968507790681443494932804976811543680463259938693076235070999518295129581121235707245383354826190752395158273098248180549665897909168867984071707793705959045775840910473413109604194111357756620727337797833203797301137672658535747710279781409721309612142393854737462769615041307952837372882050658719152259765084027796991761175393006725492491229845082362975568722711065849435533850494532638736489804606655979954360169503092790092450057856477235876198848986034412195340795369002996411974549060741600978859537660722905160772428590070901156639138364299041220826769629797867649032356499981990765997439870548648769091024911927099968275697011368762244046402960383700066212734577664709711326374656811502985863032260337383421358423937896114617192083071953915643782093641496780334152464507396683173198363362743392555311712019454146844880895622417898031894341231284027858378289009624209541345002101072736323285272576209646851994468240550629391742053301706461917215178844296705314335503772310709716080285145314144106105023117310877779933248932087727229897821330120834074305604998159963202687793307156940302439156118926767517249511766526248547096041991473113657920697330996088897286789780735587578500623575157123771653042063631002703129296694025421967877168846655727580898306467662007014679585693082220620905330827782226503112520278733512519159918893900284319218166686548434879621972211763904959895793607330943697457628943200384117552941594754747183936381144125610351023459581080768558985657007445308909428669251190101718122826689349269528261052518556736045877702288147821446968500918347219741420546128072347950059811766364526150190788545471193803557145930744635656260752787518824386409506964649815131170591457990619376560858650175616864501924098327235724333688813080022186368700209641119724303603558649793773314916749593151188673535025505982303047060284740458456676849620934506396302909441632516408692889814507247877727673378033828929504978384342943766566737297587430575141036417476861639624198941904730996100228428079444920026904845254139188246001559089131943255610365769362364161784646693141456109984038312265504115251494445380042090428718182468431624610552637677520970104063944687837375017436089751693486887651283453677552786547090231542029453873076141196649767521919808902105772633472397958968722923357769041244458682297806209887089816018179521454920370956252850733023255060096611329479148443416687429872654204083552056456404421174124065041932362831296643126330768715450444950733554418200793669701331244638824360062439816712409346806322169771701563590417609841261977801052586956634654144702511135382841010278579543061802357275500930513955637771043922799597114118278203358118398952338720119626666828781215343331193353019800652511924103594315072427251589774226901431325149775220621148653209528291784172678852791825950189428306645453380829438548491390660090152646315666940813051689857738445716110134773528439558663918031477128997248977232695083095920860316390860179422146804892537147135669490647597566350405076105930300153453613446834614136284840473063909580064862482211399539962122107992774053203059756987131501429238941821989218445861496845306346078287058864262560349767113385390753047360747520569725532663517964059488138127648519130232826129551720747594498863925111049785977410104647258831744969489273332281068408949475978706769012216951869658194406136694310323411619613160554381608728305543504819071159752742665917363693001980988797627218662628543311906086034280619151845297823703639898449414417889008602782220998390227472837967411429578924346545640402855167478372538831386154780508035236893583332887355879794886804980971406868936719416711504307402575102269081707385928535837390976424975922421061832372517021428320986753744507133218963666908565634963306077455683011837149400258404997766113525532847665618870592978212729899729592794781820428719807102278646183807006401083138975677112754136221127444534535584959769252575758312999039536959893249951324106784265611556743660088737484274038234811784911002123537108015334407708175281579422928548731689863980071896268684985779061942582000173178473797975815609269087287850270024414741281953578873964745859459899535543412801653553049058528794674398220606230386688852700505218904927782197514115595435549125326115087432280435609563176116321811794164884206928474315699133677787956913705592704959893911100786224112449931719539890308215307126971807352814294437374058180589784287101566325873726600012296180403780429093175160473979931236882466314524590792512088916974765430245705320638670468411054034201437664442213212750799846299157010147106552946146746392249574530619682203425444816247545977269653430250686824205288099692448923652171403817749282935917315481284919621433304080904306867233682060716291289398517406255904282247558159509102324206160816363511440953267967974466214658121897383725705201831800678505181233270743236051760236565304605919728246762046497950757124332306210615236617229324468286251110577832854712371857906482302429199129753477340618812393224405123793229248698239302094605799468502209356458018864737205798950819968285087908120645175464792846657029993496146354533816989879012073959534299458051884682918835631136138879631316173442207506218212945047503433730640140356614106403320867621443183928438969994268286836082535591242751488383392264668222963323657488981599104902374571278077062853236895690028469742954774248422335523859049299225453318270693966088603518491166875108552006265340966412611220069290556369052744064893640087015171662929356529921474420793873710647399136453402185931518201576110059405556600166318190916348212818643068418256991194316266715898588673650488980580832972145195811525832974358064432698289209364284959616975339927502383832695801109608954786457256109785378297307074918168744735731189049849490781632210127110919398357638892753131749978321368280932894349330930087868884127092076359007648065118301317440813138170776478562086983456849957696333241556699085937149528437303782174166781012624737754844959408277598042857813775448446192929537153359741871355556678028606484917974827559022377376189703770332489774349235376523557139076431488967144133099539679871046284747721772185865851985971282165739148574494328320308464163956096301047370473988450307936956928683464113764226308568695688152053749196294562881085987015910764955019272667378276517237450013662421051146709184898952269727656206976263055094938932099216377529415335060027109430018977339221845390337351007942764665232509045377940478212355620488638969640291029182673024368888013982750049655688955540362739754118359277009094291839958396298535952123465573707751680432023872401008786292362558484920221296055948232317635214207117650427699747801290249150914873347204981208353486521246233538858471700470120592394582541522312967601307268280232044633644234100026474341568399123881048049819491200940244895720301881220640996997340843736095812449945913231793359333819197360248853375641030435643732302001328359990615298394916710687997693926699033522064083729586994304357670917169796698442332656830732550000321312902706719106342428311390049478179307304556219943912072209495471916547109605404919944186051724981471812994063119290173738101176617356976495636675620278895592099504686163440305250658681735840269428736633431167832903837475658050990783985384926064721246565130660487673608585790218386643241627198210378772796337736742692945663985470529377745854692207002046330357343505517537014050310355526578082729897049230547545589009275410944504014157125357682801074915174627928533783099570631952876838237806368177841661186334747789420166190186143388804514884174361681454810362321037643274595653364629397295294049952661691181657740018116146497654407589150912557599100855273107733703213603505619407350405223414533224306604743600257212590127202517146952605462439215815151732661454812243619860357386922465403688559787750083268386930674253759349376972691382532780570135683441862315010318955128705494038594760949278590520009881447715839714713971813720554960331191642239195313230213875992717401904622413925914800620171561815889352945121978193704745708538695427900233080410588007250947512318930796844637224171170594606197614751977323896101315556406372309310279476973938229476346893933755946893665094049910252612163538072005644241026471164639800490998535570282059396054554479255558624918709232180130454102936332893619326596350851413637207293142767763267817840066780089558654877782630822818446508158509625695020697797889664140551101421185533444015948880284701657904464926309216120238068566472631611326995533585414320547442896728173291714010643730593960222482733969720865809194288803963344344876467583385597351333330628439786357062196382217705500672607607570202305548328439335937369624085404957344415141889143812206076832329063384332685935928226648361622876815670931303789678327741487845287838232474038340893449427806045589018183673133602271167285304427194507315740913600066356089181219040305019319028163972135790696025211929562455952835850442627787993214468221041325612271290302469610374855134599106662606082143546126463790846952338680559237822828610361386416013753920426888371192602742087474507782730180882648297991489233434653363930327991816476995529468892904060335470265188317825821391915073117022336839564945335630414192442838503954209073337511117053790819768061378846157004292392264788138228486672543415580694421193506836000488465561599083339184724263183698928130695654949153165010313216361224018298711517222401523368101476246169896417259748838727189598765602350324828709741468793415378708814573190327920453219231685852735108372055942456601545647944675449566859142997988233179819059574125368681032194798082603876241044848730208905065871934264174092007936669883601462309762759844113071525758916288010581709353072588887654386253201848624931923638568216562603110434528313030704972291334873033240933736956347974889824930017415805659182123288343858101250171537305398462043432455721482088547523494730467761429282915391485852688505423074450548192619166975975031503447208211845313907683486006908772752077246485706597636740936173143436990399498908375710246545650814962015988805204483379491707040848303909417512426275869868668644293498242419667403627076032399201407183071270759837132000712447159523642782162488472933913713634046138974088894178399320090051543608421618891328957740354384456107645016010462709579098652495342014766016330458293537653454523438667413798731255017029554582809547897542497367109038598264606895622241257303208140890607025206140457815282368504505765710043804228592032720729190222134651835930255942940875306994701101153416476785623543575023993736414532895773499876167502240919794121893188059017977444329403624038551082491954751841177014150820554999148803286500065069030165028455616533514890711974194172310029663247936640825364542104897640445108081123906368188594908660418340025631562661211506365309297219580687177632051461355581309500814563826112416521487163593643553646268872746276680368630680088231249970572706496265335285424273723449757482776061300818063419639083097882249478922949525891665782610044424440110326748539620120023397129834624242363283711074267309902126029110038109050751840523266273905031934856015485510632624318778970878895198168073096354223096005536267735905099473408744371024816727970009494589707630185344952680106730984246828848883760016695887137355969244555238536396178788134209309376484848406842940499731494663578455826688245825356635393289729316700066238128368519670627697889769929009597838069557440769080950069594659578325366066060213000525012998145215099629307110700615796004759918829827472751877492472674770755413679265775060149528336859838085353420874215682758801259992855903410097963019943741001394975591822918846705741010634931594527954742032057295356596869586863097328488381174243827058441735659667485315202886191192125286398739560928127513223214119754229343092375569339614672740517569529376699061052365448344078610425576694541873486379356070861240473688356773437140126350120823765176390562050604076894729400293162079760342896846897639867830553941515230713725560502914671175123451932131962571791940911728951123948113598860588062424037835751996487088330150679210175429060531418836978611027896830689666851868410470182364780700615529883149883111601949965815038674390467105247175993726709203381051984777006122752302698038537619917731907133105816779008651480172440446403764720673784583395382889380902941273987910475254258486561698048543296782281040453997661165123290729161619992628751086519341731116513305659182981762584769428708454819029344222186027977405519291266188948708010515922860149238393490889782166965109499761673179583522105791358724355029782111425280584380959770472177893827382916471882671437865821461326011263516554280516418422188264141890686619186492751718984735037496602686033671961304915922609442146773092074476794711917820209913226872184947548378003848726148872742881265579174794634151444545105599464567614478293387968015412886418098284885525959617399177657635267081989985408930744564199296902459275405143647525648661932959903068323866757518479741015342911416508753572892479684280248440220211898390243430190746592470563991910024225814399068391457857458095344096826158489731615822039837691005171654390590093326827586419753439483771905973079465029210363641972615923872187876095687197681934481955852567024141433671590889694204781798936556351775101591005026585947279448642317311892727153525046034081896227383114600546852406398855471859684088277722162250586368419379964112646321070639818773794369650252104438622320671517228411475433482803041707675438555447584321271846396281391925884972509051040944134450429845346071848875654240709690138592611645519676563708429710676494635766201285381926791204110977805857352062737510466943591592074904378966129808716274322385039032007477854211063899544954185997641428116395197239708078986048758264126544825149923227286176571389697334537835963603962709038002668921324389159009375225033651171937770657226295341257068980907793198879997076783263303670667342657925395849950582363998610492878479976185891384024744790742355981796013254960652684988733518397287191251899388324341602608356164496670902390042273216221931567939944001215159910054381084520081133103207553492484487369268314444466610780275891777468369344585045949963237156043800258227618908603074550819931892899703285549507330240121766349515315827830897786432254556221744305752825143708087184314470811004510108612122699931396969361066523608721126359012344828262284427191281973187269761974740398071778378188160519801862257232970224762494767912932684020188061795236229174601398576604233579094407723017353015337974435643738584248250538061547193075224429309117207447677149522141919390974201716026970557825836923707297811545552570788004955666915477901830719591663516687057984336951611189153751912396714116378197000784953115386326766369269172016978409040396969804861828436417776804088449208439901095951205751340861060375353408155737087188313898337656322533650946010308686111901241541794900659835366926383515058402026098259570385429145865025692157987309807064597082326377138235585737704225628144262793497769429358804020882742028263786443615935817930817858306265712263479452174065216410798029333573961137404301928294367884626832432449078812684787281988676202931062510264948586549463964789154366240635570346688477784815271412470430646040615614277320107003575855033995279377529716156628381118518085523414187577256025217995103662771477552291036839539792329375184700131215428652464111526297830742328651189481978920924682746392250346179819781021313400022272303222234731521016033826145645816472110340883197207109422849637006090510260943044730126801795349152894613046101033061811314821366141874985466628809585678299308824993966655499624380015821082410781190328189506855057581990908848597095494573176672201417764187253816862426293852974092626551536758155537683368451820154793964862810533857810979434793077956125541240828563089647076354827276586047900779183041806574320855302776686899978897939486987950729652971448050889517660684386673056662911929857913206598752762097197279390208473846210277152094212386266930256260451209117402079233658157593274696841906354187366092529138116574357045728290417433832596884391356956442617823006949118156994294295529170211353842468704890572313005646106202029653246628477843902025194715815133791174898257040115532858624973690714844800747184719290671002133191274834310662201874141841328708920709275866745037664169280121112867057832132585948539987132879098472640550013972043153470930436509718084070853723316111111611632600262171748813737621046013600544051850633175245231989785291065646466038278748870331134307620041356514295482843502245454400571392386492526283423907951705366640483826875013469850263767974528926285288366544314868036628329638912254207094687335597669512007687507292940623176435604796651807847095408991068514998003358735387989422028901542800717906482276185298683079286137204396993726503610285463352157718364571843381950031926272352293654343387522809514152498052577486366048613580539162662183475105825647260311633442002377527140625112075332294909525522330744664115572260242435895269482927435844022622001466247093866533879048392320516224276433339282642640953964341822416705658461244760448817737705782669080880834418822622611342632727419248415651121035047131961583094994438779439078380664656207143187309895280874153167621657602227990850199615587578332393883365169478142077533262283694526612005465820771400826060398839255150948861553177333447506822679211849690448880479070102043288205874672361672971246062341973369704807867768609989464712379097525706498042381815865399434983035941162258347729020489356838477197804973214911448748749915616679253857438010864500220134843719609727912761136925035123155282535741655826107266099467657016111855684257826878422197833994329148734893923892153298966294232703135845615804723993624827409373966761563257981994036006655039613941881183164267144485664874468348587099434743710128859267552473831462181434321232124758618476925803128913233878664527525204324484796532776273320171351979849530142473805976430318655810403609897537469226336015596525652284888167037460054235043655813438329870872734142062859147847007274999414885129441657918212383876056572545671794085637289277002790218604788423519924573051811976377731594412994393860534559159658127123862955315918182841923881357245009246238507097741891437575676886206936433608263660374355173185026954239766173038826275043838965247160428689739548061640664606565379050539422795708801840829664956978192406737307076253014257542221763860230431809477056758905681723033326311408802886092880151777469082375063137750925275331638009836786645991949881018108222446858443984865972449621097999331605268587810061927125889694400669979755648800940895626242917531834388920035663113368763931463847812763130237825562198311791061780856687903309789539747505239545316630638169559777653347655949908779202359718666623572487055558216484036084925217803431104356647417600193631613474196113126657206064282217690428541246560204561459484317744683213906021267727411189443675804442911583757423572500214191467493342871160840582639470485636370375679604797073490813681083838562113841391587052553615073991983125473434527404596547926972539542447555990332809716643578039646945749813368621152410490288581779206318208255069166455507840899628333174744873951607229399258854694188637978240144635295264982572856632103053550891057171748674115218494774077589151115819489068851971959768129214023511454382738867557288320426608338030759515727545577639726238470674634011626346953231815229549718996906470438903536574430644436472716449550868519871817092814068746449470806856174570885105064766494332205391085097539987897980672278869943134632799032372604933150163386774039430519493297142505321117669011820293604482694166301309801111227443654953271242388534939973277749999335296667138307969441135719079969506099821923206878892624416110175909254904610286553512032488285673735148429324009831633211264460376172046209384270528903772251057643968938983722779640468452705694321085455273829462711022737243290606294601651732654594463569861350966095209962038508010899673666470073918705760679801337058347046567503369379598928154437380765511031719081985901371088639600700705631873099251480947989238619052479230983309717938226245725600119571130722386790431255742179135633111146646083268382596762356018472772209198013121983224179079476134977421748168833934278876403014334318798493417716613256506422668264638388429786875443810986754386459491846082078633346046469418429778813833857755519670005669840456587642130852057050148314568259387702428619224671173187370822224627538313365937868201435535126600146246249435880806572693573084485615073901842761167215162204840459913839674251648
10LETa=1:LETg=1/SQR220LETta=a30LETa=(a+g)/240LETg=SQR(ta*g)50IFa<taTHENGOTO2060PRINTa
0.84721309
/* Calculate the arithmethic-geometric mean of two positive * numbers x and y. * Result will have d digits after the decimal point. */define m(x, y, d){auto a, g, o o=scalescale= d d=1/10^ d a=(x+ y)/2 g=sqrt(x* y)while((a- g)> d){ x=(a+ g)/2 g=sqrt(a* g) a= x}scale= oreturn(a)}scale=20m(1,1/sqrt(2),20)
.84721308479397908659
AGM←{(|𝕨-𝕩)≤1e¯15?𝕨;(0.5×𝕨+𝕩)𝕊√𝕨×𝕩}1AGM1÷√2
0.8472130847939792
#include<math.h>#include<stdio.h>#include<stdlib.h>doubleagm(doublea,doubleg){/* arithmetic-geometric mean */doubleiota=1.0E-16;doublea1,g1;if(a*g<0.0){printf("arithmetic-geometric mean undefined when x*y<0\n");exit(1);}while(fabs(a-g)>iota){a1=(a+g)/2.0;g1=sqrt(a*g);a=a1;g=g1;}returna;}intmain(void){doublex,y;printf("Enter two numbers: ");scanf("%lf%lf",&x,&y);printf("The arithmetic-geometric mean is %lf\n",agm(x,y));return0;}
Original output:
Enter two numbers: 1.0 2.0The arithmetic-geometric mean is 1.456791
Task output, the second input (0.707) is 1/sqrt(2) correct to 3 decimal places:
Enter two numbers: 1 0.707The arithmetic-geometric mean is 0.847155
/*Arithmetic Geometric Mean of 1 and 1/sqrt(2) Nigel_Galloway February 7th., 2012.*/#include"gmp.h"voidagm(constmpf_tin1,constmpf_tin2,mpf_tout1,mpf_tout2){mpf_add(out1,in1,in2);mpf_div_ui(out1,out1,2);mpf_mul(out2,in1,in2);mpf_sqrt(out2,out2);}intmain(void){mpf_set_default_prec(65568);mpf_tx0,y0,resA,resB;mpf_init_set_ui(y0,1);mpf_init_set_d(x0,0.5);mpf_sqrt(x0,x0);mpf_init(resA);mpf_init(resB);for(inti=0;i<7;i++){agm(x0,y0,resA,resB);agm(resA,resB,x0,y0);}gmp_printf("%.20000Ff\n",x0);gmp_printf("%.20000Ff\n\n",y0);return0;}
The first couple of iterations produces:
0.8530.840
Then 7 iterations produces:
0.84721308479397908660649912348219163648144591032694218506057937265973400483413475972320029399461122994212228562523341096309796266583087105969971363598338425117632681428906038970676860161665004828118872189771330941176746201994439296290216728919449950723167789734686394760667105798055785217314034939830420042211921603983955359509819364129371634064602959996797059943435160203184264875695024217486385540598195458160174241788785419275880416271901208558768564832683414043121840080403580920455949431387781512092652225457439712428682076634095473367459962179266553534862568611854330862628728728756301083556319357066871478563908898211510883635214769697961262183294322841786811376844517001814602191369402702094599668351359632788080427434548174458736322002515395293626580661419836561649162625960743472370661690235308001737531284785255843063190745427493415268579065526940600314759102033274671968612479632551055464890282085529743965124994009662552866067580448735389218570140116771697653501408495247684899325732133702898466893919466586187375296638756226604591477704420468108925658440838032040910619003153706734119594101007474331059905505820524326009951692792417478216976781061683697714110739273343921550143022007087367365962272149258776192851052380367026890463909621907663644235538085902945234065190013342345105838341712180514255003923701111325411144612628906254133550526643653595824552156293397518251470650134641047056979355681306606329373345038710977097294875917179015817320281578288487149931340815493342367797044712785937618595085146677364554679201615934223997142984070788882279032656751596528435817795727284808356489963504404140734226110183383546975962663330422084999852300742703930277243474979717973264552546543019831694968461098690743905068013766119252919770938441299707015889493166661161994592265011311183966352502530561646431587208454522988775475177272747656721648982918239238895207207642839710884705960356921992921831901548141280766592698294464457149239666329973075813904957622438962423175209507319018424462442370986427281149511180822826053862484617675180140983127497257651983756492356902800216174905531427208153439540595563576371127281657059737337442970039056040156388663072225700389230159112376960121580081779077863351240862431073571583765926504546652787337874444834406310244757039681255453982266430353416413035613801634165575265589752944521166873451220191227466733191571240763753821106968141076926390074833175743396752319660330864973571383874196098983832202882694882191302819366949954422240697276168621369511657838885012199096160655454611543253148164249332694797004159491476323112920593516518997943350045976288217292625918089405508431466393782548335139550190653370872062064024077056075848796499843651592728264534428636615419142585777106756185017278033287175195189305031805505245426022335522900771418128798654351187918006356279593624768267786412249460338126082628254098895312527677534656243279214511229555516031818433133692961723041783855157125567404983416665926969580008953724573057694542275372160209687191470398878466367243262706191127071716590824640041679941120405657103640830002419294398553073994656539677810492701055410359513339432199925066676202078394695553760551796401009749218856311301017813888578793813172095948062539201300983650287917695827985905279947721941797997024943062158419468885328115497721579960194409623477686144085075739284298823759396823223670580334134774623112897625859324376631778974911077261909704489522204509630725515590093824904021364807792034767215048568446022554409992826163174312642285787628983380650722023010371753149263504631060188573772567006618381290580638954508127031311371043716135833488065833955431217901348398833216413057635244712511539472066670330101348716516324113828817639839629526121141263219795965098656786755250760760424095907517523021946104532564333249614901253533329223723868948127885020135966305376055849358928391630469403887854960027471487197801457659579049585802260066099524967364324966833461760106608156706975142381866503610838852209761655002516073114992161294775790199729248689638220603808760276281672370166819106633585775154650381334236722347642026558565588464160102105404898556187114735884976378406486426798186504486319077470382286711435151123003607086574298864771466747337501143458188527970060562117246921748471806948662511994728934442703783046207073549380528727206215606307188286858056452111069670802856990698257691772209986719599685077906814434949328049768115436804632599386930762350709995182951295811212357072453833548261907523951582730982481805496658979091688679840717077937059590457758409104734131096041941113577566207273377978332037973011376726585357477102797814097213096121423938547374627696150413079528373728820506587191522597650840277969917611753930067254924912298450823629755687227110658494355338504945326387364898046066559799543601695030927900924500578564772358761988489860344121953407953690029964119745490607416009788595376607229051607724285900709011566391383642990412208267696297978676490323564999819907659974398705486487690910249119270999682756970113687622440464029603837000662127345776647097113263746568115029858630322603373834213584239378961146171920830719539156437820936414967803341524645073966831731983633627433925553117120194541468448808956224178980318943412312840278583782890096242095413450021010727363232852725762096468519944682405506293917420533017064619172151788442967053143355037723107097160802851453141441061050231173108777799332489320877272298978213301208340743056049981599632026877933071569403024391561189267675172495117665262485470960419914731136579206973309960888972867897807355875785006235751571237716530420636310027031292966940254219678771688466557275808983064676620070146795856930822206209053308277822265031125202787335125191599188939002843192181666865484348796219722117639049598957936073309436974576289432003841175529415947547471839363811441256103510234595810807685589856570074453089094286692511901017181228266893492695282610525185567360458777022881478214469685009183472197414205461280723479500598117663645261501907885454711938035571459307446356562607527875188243864095069646498151311705914579906193765608586501756168645019240983272357243336888130800221863687002096411197243036035586497937733149167495931511886735350255059823030470602847404584566768496209345063963029094416325164086928898145072478777276733780338289295049783843429437665667372975874305751410364174768616396241989419047309961002284280794449200269048452541391882460015590891319432556103657693623641617846466931414561099840383122655041152514944453800420904287181824684316246105526376775209701040639446878373750174360897516934868876512834536775527865470902315420294538730761411966497675219198089021057726334723979589687229233577690412444586822978062098870898160181795214549203709562528507330232550600966113294791484434166874298726542040835520564564044211741240650419323628312966431263307687154504449507335544182007936697013312446388243600624398167124093468063221697717015635904176098412619778010525869566346541447025111353828410102785795430618023572755009305139556377710439227995971141182782033581183989523387201196266668287812153433311933530198006525119241035943150724272515897742269014313251497752206211486532095282917841726788527918259501894283066454533808294385484913906600901526463156669408130516898577384457161101347735284395586639180314771289972489772326950830959208603163908601794221468048925371471356694906475975663504050761059303001534536134468346141362848404730639095800648624822113995399621221079927740532030597569871315014292389418219892184458614968453063460782870588642625603497671133853907530473607475205697255326635179640594881381276485191302328261295517207475944988639251110497859774101046472588317449694892733322810684089494759787067690122169518696581944061366943103234116196131605543816087283055435048190711597527426659173636930019809887976272186626285433119060860342806191518452978237036398984494144178890086027822209983902274728379674114295789243465456404028551674783725388313861547805080352368935833328873558797948868049809714068689367194167115043074025751022690817073859285358373909764249759224210618323725170214283209867537445071332189636669085656349633060774556830118371494002584049977661135255328476656188705929782127298997295927947818204287198071022786461838070064010831389756771127541362211274445345355849597692525757583129990395369598932499513241067842656115567436600887374842740382348117849110021235371080153344077081752815794229285487316898639800718962686849857790619425820001731784737979758156092690872878502700244147412819535788739647458594598995355434128016535530490585287946743982206062303866888527005052189049277821975141155954355491253261150874322804356095631761163218117941648842069284743156991336777879569137055927049598939111007862241124499317195398903082153071269718073528142944373740581805897842871015663258737266000122961804037804290931751604739799312368824663145245907925120889169747654302457053206386704684110540342014376644422132127507998462991570101471065529461467463922495745306196822034254448162475459772696534302506868242052880996924489236521714038177492829359173154812849196214333040809043068672336820607162912893985174062559042822475581595091023242061608163635114409532679679744662146581218973837257052018318006785051812332707432360517602365653046059197282467620464979507571243323062106152366172293244682862511105778328547123718579064823024291991297534773406188123932244051237932292486982393020946057994685022093564580188647372057989508199682850879081206451754647928466570299934961463545338169898790120739595342994580518846829188356311361388796313161734422075062182129450475034337306401403566141064033208676214431839284389699942682868360825355912427514883833922646682229633236574889815991049023745712780770628532368956900284697429547742484223355238590492992254533182706939660886035184911668751085520062653409664126112200692905563690527440648936400870151716629293565299214744207938737106473991364534021859315182015761100594055566001663181909163482128186430684182569911943162667158985886736504889805808329721451958115258329743580644326982892093642849596169753399275023838326958011096089547864572561097853782973070749181687447357311890498494907816322101271109193983576388927531317499783213682809328943493309300878688841270920763590076480651183013174408131381707764785620869834568499576963332415566990859371495284373037821741667810126247377548449594082775980428578137754484461929295371533597418713555566780286064849179748275590223773761897037703324897743492353765235571390764314889671441330995396798710462847477217721858658519859712821657391485744943283203084641639560963010473704739884503079369569286834641137642263085686956881520537491962945628810859870159107649550192726673782765172374500136624210511467091848989522697276562069762630550949389320992163775294153350600271094300189773392218453903373510079427646652325090453779404782123556204886389696402910291826730243688880139827500496556889555403627397541183592770090942918399583962985359521234655737077516804320238724010087862923625584849202212960559482323176352142071176504276997478012902491509148733472049812083534865212462335388584717004701205923945825415223129676013072682802320446336442341000264743415683991238810480498194912009402448957203018812206409969973408437360958124499459132317933593338191973602488533756410304356437323020013283599906152983949167106879976939266990335220640837295869943043576709171697966984423326568307325500003213129027067191063424283113900494781793073045562199439120722094954719165471096054049199441860517249814718129940631192901737381011766173569764956366756202788955920995046861634403052506586817358402694287366334311678329038374756580509907839853849260647212465651306604876736085857902183866432416271982103787727963377367426929456639854705293777458546922070020463303573435055175370140503103555265780827298970492305475455890092754109445040141571253576828010749151746279285337830995706319528768382378063681778416611863347477894201661901861433888045148841743616814548103623210376432745956533646293972952940499526616911816577400181161464976544075891509125575991008552731077337032136035056194073504052234145332243066047436002572125901272025171469526054624392158151517326614548122436198603573869224654036885597877500832683869306742537593493769726913825327805701356834418623150103189551287054940385947609492785905200098814477158397147139718137205549603311916422391953132302138759927174019046224139259148006201715618158893529451219781937047457085386954279002330804105880072509475123189307968446372241711705946061976147519773238961013155564063723093102794769739382294763468939337559468936650940499102526121635380720056442410264711646398004909985355702820593960545544792555586249187092321801304541029363328936193265963508514136372072931427677632678178400667800895586548777826308228184465081585096256950206977978896641405511014211855334440159488802847016579044649263092161202380685664726316113269955335854143205474428967281732917140106437305939602224827339697208658091942888039633443448764675833855973513333306284397863570621963822177055006726076075702023055483284393359373696240854049573444151418891438122060768323290633843326859359282266483616228768156709313037896783277414878452878382324740383408934494278060455890181836731336022711672853044271945073157409136000663560891812190403050193190281639721357906960252119295624559528358504426277879932144682210413256122712903024696103748551345991066626060821435461264637908469523386805592378228286103613864160137539204268883711926027420874745077827301808826482979914892334346533639303279918164769955294688929040603354702651883178258213919150731170223368395649453356304141924428385039542090733375111170537908197680613788461570042923922647881382284866725434155806944211935068360004884655615990833391847242631836989281306956549491531650103132163612240182987115172224015233681014762461698964172597488387271895987656023503248287097414687934153787088145731903279204532192316858527351083720559424566015456479446754495668591429979882331798190595741253686810321947980826038762410448487302089050658719342641740920079366698836014623097627598441130715257589162880105817093530725888876543862532018486249319236385682165626031104345283130307049722913348730332409337369563479748898249300174158056591821232883438581012501715373053984620434324557214820885475234947304677614292829153914858526885054230744505481926191669759750315034472082118453139076834860069087727520772464857065976367409361731434369903994989083757102465456508149620159888052044833794917070408483039094175124262758698686686442934982424196674036270760323992014071830712707598371320007124471595236427821624884729339137136340461389740888941783993200900515436084216188913289577403543844561076450160104627095790986524953420147660163304582935376534545234386674137987312550170295545828095478975424973671090385982646068956222412573032081408906070252061404578152823685045057657100438042285920327207291902221346518359302559429408753069947011011534164767856235435750239937364145328957734998761675022409197941218931880590179774443294036240385510824919547518411770141508205549991488032865000650690301650284556165335148907119741941723100296632479366408253645421048976404451080811239063681885949086604183400256315626612115063653092972195806871776320514613555813095008145638261124165214871635936435536462688727462766803686306800882312499705727064962653352854242737234497574827760613008180634196390830978822494789229495258916657826100444244401103267485396201200233971298346242423632837110742673099021260291100381090507518405232662739050319348560154855106326243187789708788951981680730963542230960055362677359050994734087443710248167279700094945897076301853449526801067309842468288488837600166958871373559692445552385363961787881342093093764848484068429404997314946635784558266882458253566353932897293167000662381283685196706276978897699290095978380695574407690809500695946595783253660660602130005250129981452150996293071107006157960047599188298274727518774924726747707554136792657750601495283368598380853534208742156827588012599928559034100979630199437410013949755918229188467057410106349315945279547420320572953565968695868630973284883811742438270584417356596674853152028861911921252863987395609281275132232141197542293430923755693396146727405175695293766990610523654483440786104255766945418734863793560708612404736883567734371401263501208237651763905620506040768947294002931620797603428968468976398678305539415152307137255605029146711751234519321319625717919409117289511239481135988605880624240378357519964870883301506792101754290605314188369786110278968306896668518684104701823647807006155298831498831116019499658150386743904671052471759937267092033810519847770061227523026980385376199177319071331058167790086514801724404464037647206737845833953828893809029412739879104752542584865616980485432967822810404539976611651232907291616199926287510865193417311165133056591829817625847694287084548190293442221860279774055192912661889487080105159228601492383934908897821669651094997616731795835221057913587243550297821114252805843809597704721778938273829164718826714378658214613260112635165542805164184221882641418906866191864927517189847350374966026860336719613049159226094421467730920744767947119178202099132268721849475483780038487261488727428812655791747946341514445451055994645676144782933879680154128864180982848855259596173991776576352670819899854089307445641992969024592754051436475256486619329599030683238667575184797410153429114165087535728924796842802484402202118983902434301907465924705639919100242258143990683914578574580953440968261584897316158220398376910051716543905900933268275864197534394837719059730794650292103636419726159238721878760956871976819344819558525670241414336715908896942047817989365563517751015910050265859472794486423173118927271535250460340818962273831146005468524063988554718596840882777221622505863684193799641126463210706398187737943696502521044386223206715172284114754334828030417076754385554475843212718463962813919258849725090510409441344504298453460718488756542407096901385926116455196765637084297106764946357662012853819267912041109778058573520627375104669435915920749043789661298087162743223850390320074778542110638995449541859976414281163951972397080789860487582641265448251499232272861765713896973345378359636039627090380026689213243891590093752250336511719377706572262953412570689809077931988799970767832633036706673426579253958499505823639986104928784799761858913840247447907423559817960132549606526849887335183972871912518993883243416026083561644966709023900422732162219315679399440012151599100543810845200811331032075534924844873692683144444666107802758917774683693445850459499632371560438002582276189086030745508199318928997032855495073302401217663495153158278308977864322545562217443057528251437080871843144708110045101086121226999313969693610665236087211263590123448282622844271912819731872697619747403980717783781881605198018622572329702247624947679129326840201880617952362291746013985766042335790944077230173530153379744356437385842482505380615471930752244293091172074476771495221419193909742017160269705578258369237072978115455525707880049556669154779018307195916635166870579843369516111891537519123967141163781970007849531153863267663692691720169784090403969698048618284364177768040884492084399010959512057513408610603753534081557370871883138983376563225336509460103086861119012415417949006598353669263835150584020260982595703854291458650256921579873098070645970823263771382355857377042256281442627934977694293588040208827420282637864436159358179308178583062657122634794521740652164107980293335739611374043019282943678846268324324490788126847872819886762029310625102649485865494639647891543662406355703466884777848152714124704306460406156142773201070035758550339952793775297161566283811185180855234141875772560252179951036627714775522910368395398000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
The limit (19,740) is imposed by the accuracy (65568). Using 6 iterations would produce a less accurate result. At 7 iterations increasing the 65568 would mean we already have 38,000 or so digits accurate.
namespaceRosettaCode.ArithmeticGeometricMean{usingSystem;usingSystem.Collections.Generic;usingSystem.Globalization;internalstaticclassProgram{privatestaticdoubleArithmeticGeometricMean(doublenumber,doubleotherNumber,IEqualityComparer<double>comparer){returncomparer.Equals(number,otherNumber)?number:ArithmeticGeometricMean(ArithmeticMean(number,otherNumber),GeometricMean(number,otherNumber),comparer);}privatestaticdoubleArithmeticMean(doublenumber,doubleotherNumber){return0.5*(number+otherNumber);}privatestaticdoubleGeometricMean(doublenumber,doubleotherNumber){returnMath.Sqrt(number*otherNumber);}privatestaticvoidMain(){Console.WriteLine(ArithmeticGeometricMean(1,0.5*Math.Sqrt(2),newRelativeDifferenceComparer(1e-5)).ToString(CultureInfo.InvariantCulture));}privateclassRelativeDifferenceComparer:IEqualityComparer<double>{privatereadonlydouble_maximumRelativeDifference;internalRelativeDifferenceComparer(doublemaximumRelativeDifference){_maximumRelativeDifference=maximumRelativeDifference;}publicboolEquals(doublenumber,doubleotherNumber){returnRelativeDifference(number,otherNumber)<=_maximumRelativeDifference;}publicintGetHashCode(doublenumber){returnnumber.GetHashCode();}privatestaticdoubleRelativeDifference(doublenumber,doubleotherNumber){returnAbsoluteDifference(number,otherNumber)/Norm(number,otherNumber);}privatestaticdoubleAbsoluteDifference(doublenumber,doubleotherNumber){returnMath.Abs(number-otherNumber);}privatestaticdoubleNorm(doublenumber,doubleotherNumber){return0.5*(Math.Abs(number)+Math.Abs(otherNumber));}}}}
Output:
0.847213084835193
Note that the last 5 digits are spurious, asmaximumRelativeDifference was only specified to be 1e-5. Using 1e-11 instead will give the result 0.847213084793979, which is as far asdouble can take it.
usingSystem; classProgram{ staticDecimalDecSqRoot(Decimalv){Decimalr=(Decimal)Math.Sqrt((double)v),t=0,d=0,ld=1;while(ld!=d){t=v/r;r=(r+t)/2;ld=d;d=t-r;}returnt;} staticDecimalCalcAGM(Decimala,Decimalb){Decimalc,d=0,ld=1;while(ld!=d){ld=d;c=a;d=(a=(a+b)/2)-(b=DecSqRoot(c*b));}returnb;} staticvoidMain(string[]args){Console.WriteLine(CalcAGM(1M,DecSqRoot(0.5M)));if(System.Diagnostics.Debugger.IsAttached)Console.ReadKey();}}
0.8472130847939790866064991235
Even though the System.Numerics library directly supports onlyBigInteger (and not big rationals or big floating point numbers), it can be coerced into making this calculation. One just has to keep track of the decimal place and multiply by a very large constant.
usingstaticSystem.Math;usingstaticSystem.Console;usingBI=System.Numerics.BigInteger;classProgram{staticBIBIP(charleadDig,intnumDigs){// makes big constantreturnBI.Parse(leadDig+newstring('0',numDigs));}staticBIIntSqRoot(BIv,BIres){// res is the initial guessBIterm=0,d=0,dl=1;while(dl!=d){term=v/res;res=(res+term)>>1;dl=d;d=term-res;}returnterm;}staticBICalcByAGM(intdigs){// note: a and b are hard-coded for this RC taskBIa=BIP('1',digs),// value of 1, extended to required number of digitsb=BI.Parse(string.Format("{0:0.00000000000000000}",Sqrt(0.5)).Substring(2)+newstring('0',digs-17)),// initial guess for square root of 0.5c,// temporary variable to swap a and bdiff=0,ldiff=1;// difference of a and b, last differenceb=IntSqRoot(BIP('5',(digs<<1)-1),b);// value of square root of 0.5while(ldiff!=diff){ldiff=diff;c=a;a=(a+b)>>1;diff=a-(b=IntSqRoot(c*b,a));}returnb;}staticvoidMain(string[]args){intdigits=25000;if(args.Length>0){int.TryParse(args[0],outdigits);if(digits<1||digits>999999)digits=25000;}WriteLine("0.{0}",CalcByAGM(digits));if(System.Diagnostics.Debugger.IsAttached)ReadKey();}}
0.8472130847939790866064991234821916364814459103269421850605793726597340048341347597232002939946112299421222856252334109630979626658308710596997136359833842511763268142890603897067686016166500482811887218977133094117674620199443929629021672891944995072316778973468639476066710579805578521731403493983042004221192160398395535950981936412937163406460295999679705994343516020318426487569502421748638554059819545816017424178878541927588041627190120855876856483268341404312184008040358092045594943138778151209265222545743971242868207663409547336745996217926655353486256861185433086262872872875630108355631935706687147856390889821151088363521476969796126218329432284178681137684451700181460219136940270209459966835135963278808042743454817445873632200251539529362658066141983656164916262596074347237066169023530800173753128478525584306319074542749341526857906552694060031475910203327467196861247963255105546489028208552974396512499400966255286606758044873538921857014011677169765350140849524768489932573213370289846689391946658618737529663875622660459147770442046810892565844083803204091061900315370673411959410100747433105990550582052432600995169279241747821697678106168369771411073927334392155014302200708736736596227214925877619285105238036702689046390962190766364423553808590294523406519001334234510583834171218051425500392370111132541114461262890625413355052664365359582455215629339751825147065013464104705697935568130660632937334503871097709729487591717901581732028157828848714993134081549334236779704471278593761859508514667736455467920161593422399714298407078888227903265675159652843581779572728480835648996350440414073422611018338354697596266333042208499985230074270393027724347497971797326455254654301983169496846109869074390506801376611925291977093844129970701588949316666116199459226501131118396635250253056164643158720845452298877547517727274765672164898291823923889520720764283971088470596035692199292183190154814128076659269829446445714923966632997307581390495762243896242317520950731901842446244237098642728114951118082282605386248461767518014098312749725765198375649235690280021617490553142720815343954059556357637112728165705973733744297003905604015638866307222570038923015911237696012158008177907786335124086243107357158376592650454665278733787444483440631024475703968125545398226643035341641303561380163416557526558975294452116687345122019122746673319157124076375382110696814107692639007483317574339675231966033086497357138387419609898383220288269488219130281936694995442224069727616862136951165783888501219909616065545461154325314816424933269479700415949147632311292059351651899794335004597628821729262591808940550843146639378254833513955019065337087206206402407705607584879649984365159272826453442863661541914258577710675618501727803328717519518930503180550524542602233552290077141812879865435118791800635627959362476826778641224946033812608262825409889531252767753465624327921451122955551603181843313369296172304178385515712556740498341666592696958000895372457305769454227537216020968719147039887846636724326270619112707171659082464004167994112040565710364083000241929439855307399465653967781049270105541035951333943219992506667620207839469555376055179640100974921885631130101781388857879381317209594806253920130098365028791769582798590527994772194179799702494306215841946888532811549772157996019440962347768614408507573928429882375939682322367058033413477462311289762585932437663177897491107726190970448952220450963072551559009382490402136480779203476721504856844602255440999282616317431264228578762898338065072202301037175314926350463106018857377256700661838129058063895450812703131137104371613583348806583395543121790134839883321641305763524471251153947206667033010134871651632411382881763983962952612114126321979596509865678675525076076042409590751752302194610453256433324961490125353332922372386894812788502013596630537605584935892839163046940388785496002747148719780145765957904958580226006609952496736432496683346176010660815670697514238186650361083885220976165500251607311499216129477579019972924868963822060380876027628167237016681910663358577515465038133423672234764202655856558846416010210540489855618711473588497637840648642679818650448631907747038228671143515112300360708657429886477146674733750114345818852797006056211724692174847180694866251199472893444270378304620707354938052872720621560630718828685805645211106967080285699069825769177220998671959968507790681443494932804976811543680463259938693076235070999518295129581121235707245383354826190752395158273098248180549665897909168867984071707793705959045775840910473413109604194111357756620727337797833203797301137672658535747710279781409721309612142393854737462769615041307952837372882050658719152259765084027796991761175393006725492491229845082362975568722711065849435533850494532638736489804606655979954360169503092790092450057856477235876198848986034412195340795369002996411974549060741600978859537660722905160772428590070901156639138364299041220826769629797867649032356499981990765997439870548648769091024911927099968275697011368762244046402960383700066212734577664709711326374656811502985863032260337383421358423937896114617192083071953915643782093641496780334152464507396683173198363362743392555311712019454146844880895622417898031894341231284027858378289009624209541345002101072736323285272576209646851994468240550629391742053301706461917215178844296705314335503772310709716080285145314144106105023117310877779933248932087727229897821330120834074305604998159963202687793307156940302439156118926767517249511766526248547096041991473113657920697330996088897286789780735587578500623575157123771653042063631002703129296694025421967877168846655727580898306467662007014679585693082220620905330827782226503112520278733512519159918893900284319218166686548434879621972211763904959895793607330943697457628943200384117552941594754747183936381144125610351023459581080768558985657007445308909428669251190101718122826689349269528261052518556736045877702288147821446968500918347219741420546128072347950059811766364526150190788545471193803557145930744635656260752787518824386409506964649815131170591457990619376560858650175616864501924098327235724333688813080022186368700209641119724303603558649793773314916749593151188673535025505982303047060284740458456676849620934506396302909441632516408692889814507247877727673378033828929504978384342943766566737297587430575141036417476861639624198941904730996100228428079444920026904845254139188246001559089131943255610365769362364161784646693141456109984038312265504115251494445380042090428718182468431624610552637677520970104063944687837375017436089751693486887651283453677552786547090231542029453873076141196649767521919808902105772633472397958968722923357769041244458682297806209887089816018179521454920370956252850733023255060096611329479148443416687429872654204083552056456404421174124065041932362831296643126330768715450444950733554418200793669701331244638824360062439816712409346806322169771701563590417609841261977801052586956634654144702511135382841010278579543061802357275500930513955637771043922799597114118278203358118398952338720119626666828781215343331193353019800652511924103594315072427251589774226901431325149775220621148653209528291784172678852791825950189428306645453380829438548491390660090152646315666940813051689857738445716110134773528439558663918031477128997248977232695083095920860316390860179422146804892537147135669490647597566350405076105930300153453613446834614136284840473063909580064862482211399539962122107992774053203059756987131501429238941821989218445861496845306346078287058864262560349767113385390753047360747520569725532663517964059488138127648519130232826129551720747594498863925111049785977410104647258831744969489273332281068408949475978706769012216951869658194406136694310323411619613160554381608728305543504819071159752742665917363693001980988797627218662628543311906086034280619151845297823703639898449414417889008602782220998390227472837967411429578924346545640402855167478372538831386154780508035236893583332887355879794886804980971406868936719416711504307402575102269081707385928535837390976424975922421061832372517021428320986753744507133218963666908565634963306077455683011837149400258404997766113525532847665618870592978212729899729592794781820428719807102278646183807006401083138975677112754136221127444534535584959769252575758312999039536959893249951324106784265611556743660088737484274038234811784911002123537108015334407708175281579422928548731689863980071896268684985779061942582000173178473797975815609269087287850270024414741281953578873964745859459899535543412801653553049058528794674398220606230386688852700505218904927782197514115595435549125326115087432280435609563176116321811794164884206928474315699133677787956913705592704959893911100786224112449931719539890308215307126971807352814294437374058180589784287101566325873726600012296180403780429093175160473979931236882466314524590792512088916974765430245705320638670468411054034201437664442213212750799846299157010147106552946146746392249574530619682203425444816247545977269653430250686824205288099692448923652171403817749282935917315481284919621433304080904306867233682060716291289398517406255904282247558159509102324206160816363511440953267967974466214658121897383725705201831800678505181233270743236051760236565304605919728246762046497950757124332306210615236617229324468286251110577832854712371857906482302429199129753477340618812393224405123793229248698239302094605799468502209356458018864737205798950819968285087908120645175464792846657029993496146354533816989879012073959534299458051884682918835631136138879631316173442207506218212945047503433730640140356614106403320867621443183928438969994268286836082535591242751488383392264668222963323657488981599104902374571278077062853236895690028469742954774248422335523859049299225453318270693966088603518491166875108552006265340966412611220069290556369052744064893640087015171662929356529921474420793873710647399136453402185931518201576110059405556600166318190916348212818643068418256991194316266715898588673650488980580832972145195811525832974358064432698289209364284959616975339927502383832695801109608954786457256109785378297307074918168744735731189049849490781632210127110919398357638892753131749978321368280932894349330930087868884127092076359007648065118301317440813138170776478562086983456849957696333241556699085937149528437303782174166781012624737754844959408277598042857813775448446192929537153359741871355556678028606484917974827559022377376189703770332489774349235376523557139076431488967144133099539679871046284747721772185865851985971282165739148574494328320308464163956096301047370473988450307936956928683464113764226308568695688152053749196294562881085987015910764955019272667378276517237450013662421051146709184898952269727656206976263055094938932099216377529415335060027109430018977339221845390337351007942764665232509045377940478212355620488638969640291029182673024368888013982750049655688955540362739754118359277009094291839958396298535952123465573707751680432023872401008786292362558484920221296055948232317635214207117650427699747801290249150914873347204981208353486521246233538858471700470120592394582541522312967601307268280232044633644234100026474341568399123881048049819491200940244895720301881220640996997340843736095812449945913231793359333819197360248853375641030435643732302001328359990615298394916710687997693926699033522064083729586994304357670917169796698442332656830732550000321312902706719106342428311390049478179307304556219943912072209495471916547109605404919944186051724981471812994063119290173738101176617356976495636675620278895592099504686163440305250658681735840269428736633431167832903837475658050990783985384926064721246565130660487673608585790218386643241627198210378772796337736742692945663985470529377745854692207002046330357343505517537014050310355526578082729897049230547545589009275410944504014157125357682801074915174627928533783099570631952876838237806368177841661186334747789420166190186143388804514884174361681454810362321037643274595653364629397295294049952661691181657740018116146497654407589150912557599100855273107733703213603505619407350405223414533224306604743600257212590127202517146952605462439215815151732661454812243619860357386922465403688559787750083268386930674253759349376972691382532780570135683441862315010318955128705494038594760949278590520009881447715839714713971813720554960331191642239195313230213875992717401904622413925914800620171561815889352945121978193704745708538695427900233080410588007250947512318930796844637224171170594606197614751977323896101315556406372309310279476973938229476346893933755946893665094049910252612163538072005644241026471164639800490998535570282059396054554479255558624918709232180130454102936332893619326596350851413637207293142767763267817840066780089558654877782630822818446508158509625695020697797889664140551101421185533444015948880284701657904464926309216120238068566472631611326995533585414320547442896728173291714010643730593960222482733969720865809194288803963344344876467583385597351333330628439786357062196382217705500672607607570202305548328439335937369624085404957344415141889143812206076832329063384332685935928226648361622876815670931303789678327741487845287838232474038340893449427806045589018183673133602271167285304427194507315740913600066356089181219040305019319028163972135790696025211929562455952835850442627787993214468221041325612271290302469610374855134599106662606082143546126463790846952338680559237822828610361386416013753920426888371192602742087474507782730180882648297991489233434653363930327991816476995529468892904060335470265188317825821391915073117022336839564945335630414192442838503954209073337511117053790819768061378846157004292392264788138228486672543415580694421193506836000488465561599083339184724263183698928130695654949153165010313216361224018298711517222401523368101476246169896417259748838727189598765602350324828709741468793415378708814573190327920453219231685852735108372055942456601545647944675449566859142997988233179819059574125368681032194798082603876241044848730208905065871934264174092007936669883601462309762759844113071525758916288010581709353072588887654386253201848624931923638568216562603110434528313030704972291334873033240933736956347974889824930017415805659182123288343858101250171537305398462043432455721482088547523494730467761429282915391485852688505423074450548192619166975975031503447208211845313907683486006908772752077246485706597636740936173143436990399498908375710246545650814962015988805204483379491707040848303909417512426275869868668644293498242419667403627076032399201407183071270759837132000712447159523642782162488472933913713634046138974088894178399320090051543608421618891328957740354384456107645016010462709579098652495342014766016330458293537653454523438667413798731255017029554582809547897542497367109038598264606895622241257303208140890607025206140457815282368504505765710043804228592032720729190222134651835930255942940875306994701101153416476785623543575023993736414532895773499876167502240919794121893188059017977444329403624038551082491954751841177014150820554999148803286500065069030165028455616533514890711974194172310029663247936640825364542104897640445108081123906368188594908660418340025631562661211506365309297219580687177632051461355581309500814563826112416521487163593643553646268872746276680368630680088231249970572706496265335285424273723449757482776061300818063419639083097882249478922949525891665782610044424440110326748539620120023397129834624242363283711074267309902126029110038109050751840523266273905031934856015485510632624318778970878895198168073096354223096005536267735905099473408744371024816727970009494589707630185344952680106730984246828848883760016695887137355969244555238536396178788134209309376484848406842940499731494663578455826688245825356635393289729316700066238128368519670627697889769929009597838069557440769080950069594659578325366066060213000525012998145215099629307110700615796004759918829827472751877492472674770755413679265775060149528336859838085353420874215682758801259992855903410097963019943741001394975591822918846705741010634931594527954742032057295356596869586863097328488381174243827058441735659667485315202886191192125286398739560928127513223214119754229343092375569339614672740517569529376699061052365448344078610425576694541873486379356070861240473688356773437140126350120823765176390562050604076894729400293162079760342896846897639867830553941515230713725560502914671175123451932131962571791940911728951123948113598860588062424037835751996487088330150679210175429060531418836978611027896830689666851868410470182364780700615529883149883111601949965815038674390467105247175993726709203381051984777006122752302698038537619917731907133105816779008651480172440446403764720673784583395382889380902941273987910475254258486561698048543296782281040453997661165123290729161619992628751086519341731116513305659182981762584769428708454819029344222186027977405519291266188948708010515922860149238393490889782166965109499761673179583522105791358724355029782111425280584380959770472177893827382916471882671437865821461326011263516554280516418422188264141890686619186492751718984735037496602686033671961304915922609442146773092074476794711917820209913226872184947548378003848726148872742881265579174794634151444545105599464567614478293387968015412886418098284885525959617399177657635267081989985408930744564199296902459275405143647525648661932959903068323866757518479741015342911416508753572892479684280248440220211898390243430190746592470563991910024225814399068391457857458095344096826158489731615822039837691005171654390590093326827586419753439483771905973079465029210363641972615923872187876095687197681934481955852567024141433671590889694204781798936556351775101591005026585947279448642317311892727153525046034081896227383114600546852406398855471859684088277722162250586368419379964112646321070639818773794369650252104438622320671517228411475433482803041707675438555447584321271846396281391925884972509051040944134450429845346071848875654240709690138592611645519676563708429710676494635766201285381926791204110977805857352062737510466943591592074904378966129808716274322385039032007477854211063899544954185997641428116395197239708078986048758264126544825149923227286176571389697334537835963603962709038002668921324389159009375225033651171937770657226295341257068980907793198879997076783263303670667342657925395849950582363998610492878479976185891384024744790742355981796013254960652684988733518397287191251899388324341602608356164496670902390042273216221931567939944001215159910054381084520081133103207553492484487369268314444466610780275891777468369344585045949963237156043800258227618908603074550819931892899703285549507330240121766349515315827830897786432254556221744305752825143708087184314470811004510108612122699931396969361066523608721126359012344828262284427191281973187269761974740398071778378188160519801862257232970224762494767912932684020188061795236229174601398576604233579094407723017353015337974435643738584248250538061547193075224429309117207447677149522141919390974201716026970557825836923707297811545552570788004955666915477901830719591663516687057984336951611189153751912396714116378197000784953115386326766369269172016978409040396969804861828436417776804088449208439901095951205751340861060375353408155737087188313898337656322533650946010308686111901241541794900659835366926383515058402026098259570385429145865025692157987309807064597082326377138235585737704225628144262793497769429358804020882742028263786443615935817930817858306265712263479452174065216410798029333573961137404301928294367884626832432449078812684787281988676202931062510264948586549463964789154366240635570346688477784815271412470430646040615614277320107003575855033995279377529716156628381118518085523414187577256025217995103662771477552291036839539792329375184700131215428652464111526297830742328651189481978920924682746392250346179819781021313400022272303222234731521016033826145645816472110340883197207109422849637006090510260943044730126801795349152894613046101033061811314821366141874985466628809585678299308824993966655499624380015821082410781190328189506855057581990908848597095494573176672201417764187253816862426293852974092626551536758155537683368451820154793964862810533857810979434793077956125541240828563089647076354827276586047900779183041806574320855302776686899978897939486987950729652971448050889517660684386673056662911929857913206598752762097197279390208473846210277152094212386266930256260451209117402079233658157593274696841906354187366092529138116574357045728290417433832596884391356956442617823006949118156994294295529170211353842468704890572313005646106202029653246628477843902025194715815133791174898257040115532858624973690714844800747184719290671002133191274834310662201874141841328708920709275866745037664169280121112867057832132585948539987132879098472640550013972043153470930436509718084070853723316111111611632600262171748813737621046013600544051850633175245231989785291065646466038278748870331134307620041356514295482843502245454400571392386492526283423907951705366640483826875013469850263767974528926285288366544314868036628329638912254207094687335597669512007687507292940623176435604796651807847095408991068514998003358735387989422028901542800717906482276185298683079286137204396993726503610285463352157718364571843381950031926272352293654343387522809514152498052577486366048613580539162662183475105825647260311633442002377527140625112075332294909525522330744664115572260242435895269482927435844022622001466247093866533879048392320516224276433339282642640953964341822416705658461244760448817737705782669080880834418822622611342632727419248415651121035047131961583094994438779439078380664656207143187309895280874153167621657602227990850199615587578332393883365169478142077533262283694526612005465820771400826060398839255150948861553177333447506822679211849690448880479070102043288205874672361672971246062341973369704807867768609989464712379097525706498042381815865399434983035941162258347729020489356838477197804973214911448748749915616679253857438010864500220134843719609727912761136925035123155282535741655826107266099467657016111855684257826878422197833994329148734893923892153298966294232703135845615804723993624827409373966761563257981994036006655039613941881183164267144485664874468348587099434743710128859267552473831462181434321232124758618476925803128913233878664527525204324484796532776273320171351979849530142473805976430318655810403609897537469226336015596525652284888167037460054235043655813438329870872734142062859147847007274999414885129441657918212383876056572545671794085637289277002790218604788423519924573051811976377731594412994393860534559159658127123862955315918182841923881357245009246238507097741891437575676886206936433608263660374355173185026954239766173038826275043838965247160428689739548061640664606565379050539422795708801840829664956978192406737307076253014257542221763860230431809477056758905681723033326311408802886092880151777469082375063137750925275331638009836786645991949881018108222446858443984865972449621097999331605268587810061927125889694400669979755648800940895626242917531834388920035663113368763931463847812763130237825562198311791061780856687903309789539747505239545316630638169559777653347655949908779202359718666623572487055558216484036084925217803431104356647417600193631613474196113126657206064282217690428541246560204561459484317744683213906021267727411189443675804442911583757423572500214191467493342871160840582639470485636370375679604797073490813681083838562113841391587052553615073991983125473434527404596547926972539542447555990332809716643578039646945749813368621152410490288581779206318208255069166455507840899628333174744873951607229399258854694188637978240144635295264982572856632103053550891057171748674115218494774077589151115819489068851971959768129214023511454382738867557288320426608338030759515727545577639726238470674634011626346953231815229549718996906470438903536574430644436472716449550868519871817092814068746449470806856174570885105064766494332205391085097539987897980672278869943134632799032372604933150163386774039430519493297142505321117669011820293604482694166301309801111227443654953271242388534939973277749999335296667138307969441135719079969506099821923206878892624416110175909254904610286553512032488285673735148429324009831633211264460376172046209384270528903772251057643968938983722779640468452705694321085455273829462711022737243290606294601651732654594463569861350966095209962038508010899673666470073918705760679801337058347046567503369379598928154437380765511031719081985901371088639600700705631873099251480947989238619052479230983309717938226245725600119571130722386790431255742179135633111146646083268382596762356018472772209198013121983224179079476134977421748168833934278876403014334318798493417716613256506422668264638388429786875443810986754386459491846082078633346046469418429778813833857755519670005669840456587642130852057050148314568259387702428619224671173187370822224627538313365937868201435535126600146246249435880806572693573084485615073901842761167215162204840459913839674251648
#include<iostream>#include<cmath>doubleagm(doublea,doubleg,doubletolerance=1e-16){doublean=a;doublegn=g;an=(a+g)/2.0;gn=std::sqrt(a*g);while(std::abs(an-gn)>tolerance){an=(an+gn)/2.0;gn=std::sqrt(an*gn);}returnan;}intmain(){std::cout<<"Arithmetic-geometric mean of 1 and 1/√2 is "<<agm(1,1/std::sqrt(2))<<"\n";return0;}
Output:
Arithmetic-geometric mean of 1 and 1/√2 is 0.845111
Compile withg++ -std=c++20 -Wall -Wextra -pedantic agm.cpp -o agm
(nsagmcompute(:gen-class)); Java Arbitray Precision Library(import'(org.apfloatApfloatApfloatMath))(defprecision70)(defone(Apfloat.1Mprecision))(deftwo(Apfloat.2Mprecision))(defhalf(Apfloat.0.5Mprecision))(defisqrt2(.divideone(ApfloatMath/powtwohalf)))(defTOLERANCE(Apfloat.0.000000Mprecision))(defnagm[ag]" Simple AGM Loop calculation "(let[THRESH1e-65; done when error less than threshold or we exceed max loopsMAX-LOOPS1000000](loop[[angn][ag],cnt0](if(or(<(ApfloatMath/abs(.subtractangn))THRESH)(>cntMAX-LOOPS))an(recur[(.multiply(.addangn)half)(ApfloatMath/pow(.multiplyangn)half)](inccnt))))))(println(agmoneisqrt2))
8.47213084793979086606499123482191636481445910326942185060579372659734e-1
IDENTIFICATIONDIVISION.PROGRAM-ID.ARITHMETIC-GEOMETRIC-MEAN-PROG.DATA DIVISION.WORKING-STORAGESECTION.01 AGM-VARS. 05APIC 9V9(16). 05A-ZEROPIC 9V9(16). 05GPIC 9V9(16). 05DIFFPIC 9V9(16)VALUE1.* InitializeDIFFwithanon-zerovalue,otherwiseAGM-PARAGRAPH* is neverperformedatall.PROCEDUREDIVISION.TEST-PARAGRAPH. MOVE1TOA. COMPUTEG=1/FUNCTIONSQRT(2).* Theprogramwillrunwiththetestvalues.Ifyouwouldrather* calculatetheAGMofnumbersinputattheconsole,commentout* TEST-PARAGRAPHandun-comment-outINPUT-A-AND-G-PARAGRAPH.* INPUT-A-AND-G-PARAGRAPH.*DISPLAY'Enter two numbers.'*ACCEPTA.*ACCEPTG.CONTROL-PARAGRAPH. PERFORMAGM-PARAGRAPHUNTILDIFFISLESSTHAN0.000000000000001. DISPLAYA. STOPRUN.AGM-PARAGRAPH. MOVEATOA-ZERO. COMPUTEA=(A-ZERO+G)/2. MULTIPLYA-ZEROBYGGIVINGG. COMPUTEG=FUNCTIONSQRT(G). SUBTRACTAFROMGGIVINGDIFF. COMPUTEDIFF=FUNCTIONABS(DIFF).
0.8472130847939792
(defunagm(a0g0&optional(tolerance1d-8))(loopfora=a0then(*(+ag)5d-1)andg=g0then(sqrt(*ag))until(<(abs(-ag))tolerance)finally(returna)))
CL-USER> (agm 1d0 (/ 1d0 (sqrt 2d0)))0.8472130848351929d0CL-USER> (agm 1d0 (/ 1d0 (sqrt 2d0)) 1d-10)0.8472130848351929d0CL-USER> (agm 1d0 (/ 1d0 (sqrt 2d0)) 1d-12)0.8472130847939792d0
defagm(a:Float64,g:Float64)whilea-g>=Float64::EPSILONa,g=(a+g)/2,Math.sqrt(a*g)endgendpagm(1,1/Math.sqrt(2))
0.847213084793979
importstd.stdio,std.math,std.meta,std.typecons;realagm(reala,realg,inintbitPrecision=60)purenothrow@nogc@safe{do{//{a, g} = {(a + g) / 2.0, sqrt(a * g)};AliasSeq!(a,g)=tuple((a+g)/2.0,sqrt(a*g));}while(feqrel(a,g)<bitPrecision);returna;}voidmain()@safe{writefln("%0.19f",agm(1,1/sqrt(2.0)));}
0.8472130847939790866
All the digits shown are exact.
programgeometric_mean;{$APPTYPE CONSOLE}usesSystem.SysUtils;functionFabs(value:Double):Double;beginResult:=value;ifResult<0thenResult:=-Result;end;functionagm(a,g:Double):Double;variota,a1,g1:Double;beginiota:=1.0E-16;ifa*g<0.0thenbeginWriteln('arithmetic-geometric mean undefined when x*y<0');exit(1);end;whileFabs(a-g)>iotadobegina1:=(a+g)/2.0;g1:=sqrt(a*g);a:=a1;g:=g1;end;Exit(a);end;varx,y:Double;beginWrite('Enter two numbers:');Readln(x,y);writeln(format('The arithmetic-geometric mean is %.6f',[agm(x,y)]));readln;end.
Enter two numbers:12The arithmetic-geometric mean is 1,456791
>>> 200 k ? sbsa [lalb +2/ lalb *vsb dsa lb - 0!=:]ds:xlap?> 1 1 2 v /
.8472130847939790866064991234821916364814459103269421850605793726597\34004834134759723200293994611229942122285625233410963097962665830871\05969971363598338425117632681428906038970676860161665004828118868
You can change the precision (200 by default)
DuckDB can successfully run the code at#SQL on this pageafter the following alterations have been made:
With these changes, the statement becomes:
withrecursiverec(rn,a,g,diff)as(select1,1.0,1/sqrt(2),1-1/sqrt(2)unionallselectrn+1,(a+g)/2,sqrt(a*g),(a+g)/2-sqrt(a*g)fromrecwherediff>1e-15)select*fromrecwherediff<=1e-15;
┌───────┬────────────────────┬───────────────────┬────────────────────────┐│ rn │ a │ g │ diff ││ int32 │ double │ double │ double │├───────┼────────────────────┼───────────────────┼────────────────────────┤│ 5 │ 0.8472130847939792 │ 0.847213084793979 │ 1.1102230246251565e-16 │└───────┴────────────────────┴───────────────────┴────────────────────────┘
Here is a DuckDB scalar function that encapsulates the above algorithm whileeliminating the redundant computations:
createorreplacefunctionagm(a0,g0)as(withrecursiverecas(selecta0::DOUBLEasa,g0::DOUBLEasg,a-gasdiffunionallselecta,g,(a-g)asdifffrom(select((a+g)/2)asa,sqrt(a*g)asg,difffromrec)wherediff>1e-15)select(a+g)/2fromrecwherediff<=1e-15limit1);
Example:
D select agm(1, 1/sqrt(2));┌───────────────────────┐│ agm(1, (1 / sqrt(2))) ││ double │├───────────────────────┤│ 0.8472130847939792 │└───────────────────────┘
func agm a g . repeat a0 = a a = (a0 + g) / 2 g = sqrt (a0 * g) until abs (a0 - a) < abs (a) * 1e-15 . return a.numfmt 0 16print agm 1 sqrt 0.5
0.8472130847939792
We use the(~= a b) operator which tests for |a - b| < ε = (math-precision).
(lib'math)(define(agmag)(if(~=ag)a(agm(//(+ag)2)(sqrt(*ag)))))(math-precision)→0.000001;; default(agm1(/1(sqrt2)))→0.8472130848351929(math-precision1.e-15)→1e-15(agm1(/1(sqrt2)))→0.8472130847939792
defmoduleArithhGeomdodefmean(a,g,tol)whenabs(a-g)<=tol,do:adefmean(a,g,tol)domean((a+g)/2,:math.pow(a*g,0.5),tol)endendIO.putsArithhGeom.mean(1,1/:math.sqrt(2),0.0000000001)
0.8472130848351929
%% Arithmetic Geometric Mean of 1 and 1 / sqrt(2)%% Author: Abhay Jain-module(agm_calculator).-export([find_agm/0]).-define(TOLERANCE,0.0000000001).find_agm()->A=1,B=1/(math:pow(2,0.5)),AGM=agm(A,B),io:format("AGM =~p",[AGM]).agm(A,B)whenabs(A-B)=<?TOLERANCE->A;agm(A,B)->A1=(A+B)/2,B1=math:pow(A*B,0.5),agm(A1,B1).
Output:
AGM=0.8472130848351929
PROGRAM AGM!! for rosettacode.org!!$DOUBLEPROCEDURE AGM(A,G->A) LOCAL TA REPEAT TA=A A=(A+G)/2 G=SQR(TA*G) UNTIL A=TAEND PROCEDUREBEGIN AGM(1.0,1/SQR(2)->A) PRINT(A)END PROGRAM
letrecagmagprecision=ifprecision>abs(a-g)thenaelseagm(0.5*(a+g))(sqrt(a*g))precisionprintfn"%g"(agm1.(sqrt(0.5))1e-15)
Output
0.847213
USING:kernelmathmath.functionsprettyprint;IN:rosetta-code.arithmetic-geometric-mean:agm(ag--a'g')2dup[+0.5*]2dip*sqrt;1 1 2sqrt/[2dup-1e-15>][agm]whiledrop.
0.8472130847939792
:agm( a g -- m )beginfoverfoverf+2ef/frotfrotf*fsqrtfoverfover1e-15f~untilfdrop;1e2e-0.5ef**agmf.\ 0.847213084793979
AFortran 77 implementation
functionagm(a,b)implicit nonedouble precisionagm,a,b,eps,cparameter(eps=1.0d-15)10c=0.5d0*(a+b)b=sqrt(a*b)a=cif(a-b.gt.eps*a)goto10agm=0.5d0*(a+b)end programtestimplicit nonedouble precisionagmprint*,agm(1.0d0,1.0d0/sqrt(2.0d0))end
This example isincorrect. Please fix the code and remove this message.
|
import"futlib/math"funagm(a:f64,g:f64):f64=leteps=1.0E-16loop((a,g))=whilef64.abs(a-g)>epsdo((a+g)/2.0,f64.sqrt(a*g))inafunmain(x:f64,y:f64):f64=agm(x,y)
double local fn agm( a as double, g as double ) double ta do ta = a a = (a + g) / 2 g = sqr(ta * g) until ( a == ta )end fn = aprint fn agm( 1, 1/sqr(2) )HandleEvents
0.8472130847939792
packagemainimport("fmt""math")constε=1e-14funcagm(a,gfloat64)float64{formath.Abs(a-g)>math.Abs(a)*ε{a,g=(a+g)*.5,math.Sqrt(a*g)}returna}funcmain(){fmt.Println(agm(1,1/math.Sqrt2))}
0.8472130847939792
Solution:
doubleagm(doublea,doubleg){doublean=a,gn=gwhile((an-gn).abs()>=10.0**-14){(an,gn)=[(an+gn)*0.5,(an*gn)**0.5]}an}
Test:
println"agm(1, 0.5**0.5) = agm(1, ${0.5**0.5}) = ${agm(1, 0.5**0.5)}"assert(0.8472130847939792-agm(1,0.5**0.5)).abs()<=10.0**-14
Output:
agm(1, 0.5**0.5) = agm(1, 0.7071067811865476) = 0.8472130847939792
-- Return an approximation to the arithmetic-geometric mean of two numbers.-- The result is considered accurate when two successive approximations are-- sufficiently close, as determined by "eq".agm::(Floatinga)=>a->a->((a,a)->Bool)->aagmageq=snd$untileqstep(a,g)wherestep(a,g)=((a+g)/2,sqrt(a*g))-- Return the relative difference of the pair. We assume that at least one of-- the values is far enough from 0 to not cause problems.relDiff::(Fractionala)=>(a,a)->arelDiff(x,y)=letn=abs(x-y)d=(absx+absy)/2inn/dmain::IO()main=doletequal=(<0.000000001).relDiffprint$agm1(1/sqrt2)equal
0.8472130847527654
agmHelper x = match x with | (a, g, n) -> if (n == 0) then a else agmHelper(((a + g) / 2.0, sqrt(a * g), n - 1))agm x = match x with | (a, g) -> agmHelper((a, g, 20))
> agm((1.0, 0.5))0.728396
procedure main(A) a := real(A[1]) | 1.0 g := real(A[2]) | (1 / 2^0.5) epsilon := real(A[3]) write("agm(",a,",",g,") = ",agm(a,g,epsilon))endprocedure agm(an, gn, e) /e := 1e-15 while abs(an-gn) > e do { ap := (an+gn)/2.0 gn := (an*gn)^0.5 an := ap } return anendOutput:
->agmagm(1.0,0.7071067811865475) = 0.8472130847939792->
This one is probably worth not naming, in J, because there are so many interesting variations.
First, the basic approach (with display precision set to 16 digits, which slightly exceeds the accuracy of 64 bit IEEE floating point arithmetic):
mean=:+/%#(mean,*/%:~#)^:_]1,%%:20.84721308479397920.8472130847939791
This is the limit -- it stops when values are within a small epsilon of previous calculations. We can ask J for unique values (which also means -- unless we specify otherwise -- values within a small epsilon of each other, for floating point values):
~.(mean,*/%:~#)^:_]1,%%:20.8472130847939792
Another variation would be to show intermediate values, in the limit process:
(mean,*/%:~#)^:a:1,%%:210.70710678118654750.85355339059327370.84089641525371450.84722490292349420.84720126674689150.84721308483519290.84721308475276540.84721308479397920.8472130847939791
Another variation would be to usearbitrary precision arithmetic in place of floating point arithmetic.
Borrowing routines from that page, but going with a default of approximately 100 digits of precision:
DP=:101round=:DP&$::(4 : 0)b%~<.1r2+y*b=.10x^x)sqrt=:DP&$::(4 : 0)"0assert.0<:y%/<.@%:(2x:(2*x)roundy)*10x^2*x+0>.>.10^.y)ln=:DP&$::(4 : 0)"0assert.0<ym=.<.0.5+2^.yt=.(<:%>:)(x:!.0y)%2x^mif.x<-:#":tdo.t=.(1+x)roundtend.ln2=.2*+/1r3(^%])1+2*i.>.0.5*(%3)^.0.5*0.1^x+>.10^.1>.mlnr=.2*+/t(^%])1+2*i.>.0.5*(|t)^.0.5*0.1^xlnr+m*ln2)exp=:DP&$::(4 : 0)"0m=.<.0.5+y%^.2xm=.x+>.m*10^.2d=.(x:!.0y)-m*xmln2if.xm<-:#":ddo.d=.xmrounddend.e=.0.1^xmn=.e(>i.1:)a(^%!@])i.>.a^.e[a=.|y-m*^.2(2x^m)*1++/*/\d%1+i.n)
We are also going to want a routine to display numbers with this precision, and we are going to need to manage epsilon manually, and we are going to need an arbitrary root routine:
fmt=:[:;:invDP&$::(4 :0)&.>x{.deb(x*2j1)":y)root=:ln@]exp@%[epsilon=:1r9^DP
Some example uses:
fmtsqrt21.414213562373095048801688724209698078569671875376948073176679737990732478462107038850387534327641572fmt*~sqrt22.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fmtepsilon0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000418fmt2root21.414213562373095048801688724209698078569671875376948073176679737990732478462107038850387534327641572
Note that 2 root 2 is considerably slower than sqrt 2. The price of generality. So, while we could define geometric mean generally, a desire for good performance pushes us to use a routine specialized for two numbers:
geomean=:*/root~#geomean2=:[:sqrt*/
A quick test to make sure these can be equivalent:
fmtgeomean353.872983346207416885179265399782399610832921705291590826587573766113483091936979033519287376858673517fmtgeomean2353.872983346207416885179265399782399610832921705291590826587573766113483091936979033519287376858673517
Now for our task example:
fmt(mean,geomean2)^:(epsilon<&|-/)^:a:1,%sqrt21.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.7071067811865475244008443621048490392848359376884740365883398689953662392310535194251937671638207860.8535533905932737622004221810524245196424179688442370182941699344976831196155267597125968835819103930.8408964152537145430311254762332148950400342623567845108132260859749247549539022398143240041992925360.8472249029234941526157738286428197073412261156005107645536980102363039372847144997634604438906014640.8472012667468914604036314536933523979639810136120005008232957479234881918713276681075814345423535360.8472130848351928065097026411680860526526035646062556326884968790798960645780210839355209392164775000.8472130847527653667042980517799020703921106560594525833177762276594388966885185567535692987624493810.8472130847939790866070003464739940615223571103328541080031365533696674806332698203445451189894634400.8472130847939790866059979004903892114405348585862613004614139299713992816190686666825691081412247100.8472130847939790866064991234821916364814459844595577042322752416705333811261692435135571135653440750.8472130847939790866064991234821916364814458361943266658888835036489346285421002759328467177901473610.8472130847939790866064991234821916364814459103269421850605793726597340048341347597232019156777457180.8472130847939790866064991234821916364814459103269421850605793726597340048341347597231986723114767410.8472130847939790866064991234821916364814459103269421850605793726597340048341347597232002939946112290.847213084793979086606499123482191636481445910326942185060579372659734004834134759723200293994611229
We could of course extract out only a representative final value, but it's obvious enough, and showing how rapidly this converges is fun.
/* * Arithmetic-Geometric Mean of 1 & 1/sqrt(2) * Brendan Shaklovitz * 5/29/12 */publicclassArithmeticGeometricMean{publicstaticdoubleagm(doublea,doubleg){doublea1=a;doubleg1=g;while(Math.abs(a1-g1)>=1.0e-14){doublearith=(a1+g1)/2.0;doublegeom=Math.sqrt(a1*g1);a1=arith;g1=geom;}returna1;}publicstaticvoidmain(String[]args){System.out.println(agm(1.0,1.0/Math.sqrt(2.0)));}}
0.8472130847939792
functionagm(a0,g0){varan=(a0+g0)/2,gn=Math.sqrt(a0*g0);while(Math.abs(an-gn)>tolerance){an=(an+gn)/2,gn=Math.sqrt(an*gn)}returnan;}agm(1,1/Math.sqrt(2));
(()=>{'use strict';// ARITHMETIC-GEOMETRIC MEAN// agm :: Num a => a -> a -> aletagm=(a,g)=>{letabs=Math.abs,sqrt=Math.sqrt;returnuntil(m=>abs(m.an-m.gn)<tolerance,m=>{return{an:(m.an+m.gn)/2,gn:sqrt(m.an*m.gn)};},{an:(a+g)/2,gn:sqrt(a*g)}).an;},// GENERIC// until :: (a -> Bool) -> (a -> a) -> a -> auntil=(p,f,x)=>{letv=x;while(!p(v))v=f(v);returnv;};// TESTlettolerance=0.000001;returnagm(1,1/Math.sqrt(2));})();
0.8472130848351929Naive version that assumes tolerance is appropriately specified:
def naive_agm(a; g; tolerance): def abs: if . < 0 then -. else . end; def _agm: # state [an,gn] if ((.[0] - .[1])|abs) > tolerance then [add/2, ((.[0] * .[1])|sqrt)] | _agm else . end; [a, g] | _agm | .[0] ;
This version avoids an infinite loop if the requested tolerance is too small:
def agm(a; g; tolerance): def abs: if . < 0 then -. else . end; def _agm: # state [an,gn, delta] ((.[0] - .[1])|abs) as $delta | if $delta == .[2] and $delta < 10e-16 then . elif $delta > tolerance then [ .[0:2]|add / 2, ((.[0] * .[1])|sqrt), $delta] | _agm else . end; if tolerance <= 0 then error("specified tolerance must be > 0") else [a, g, 0] | _agm | .[0] end ; # Example:agm(1; 1/(2|sqrt); 1e-100)$ jq -n -f Arithmetic-geometric_mean.jq0.8472130847939792
functionagm(x,y,e::Real=5)(x≤0||y≤0||e≤0)&&throw(DomainError("x, y must be strictly positive"))g,a=minmax(x,y)whilee*eps(x)<a-ga,g=(a+g)/2,sqrt(a*g)endaendx,y=1.0,1/√2println("# Using literal-precision float numbers:")@showagm(x,y)println("# Using half-precision float numbers:")x,y=Float32(x),Float32(y)@showagm(x,y)println("# Using ",precision(BigFloat),"-bit float numbers:")x,y=big(1.0),1/√big(2.0)@showagm(x,y)
The ε for this calculation is given as a positive integer multiple of the machine ε forx.
# Using literal-precision float numbers:agm(x, y) = 0.8472130847939792# Using half-precision float numbers:agm(x, y) = 0.84721315f0# Using 256-bit float numbers:agm(x, y) = 8.472130847939790866064991234821916364814459103269421850605793726597340048341323e-01
include ..\Utilitys.tlhy:agm [ over over + 2 / rot rot * sqrt ] [ over over tostr swap tostr # ] while drop ;1 1 2 sqrt / agmpstack" " input
include ..\Utilitys.tlhy:agm %a %g %p !p !g !a$p $a $g - abs > ( [$a] [.5 $a $g + * $a $g * sqrt $p agm] ) if ;1 .5 sqrt 1e-15 agmpstack" " input
(0.847213)
// version 1.0.5-2funagm(a:Double,g:Double):Double{varaa=a// mutable 'a'vargg=g// mutable 'g'varta:Double// temporary variable to hold next iteration of 'aa'valepsilon=1.0e-16// tolerance for checking if limit has been reachedwhile(true){ta=(aa+gg)/2.0if(Math.abs(aa-ta)<=epsilon)returntagg=Math.sqrt(aa*gg)aa=ta}}funmain(args:Array<String>){println(agm(1.0,1.0/Math.sqrt(2.0)))}
0.8472130847939792
{defeps1e-15}->eps{defagm{lambda{:a:g}{if{>{abs{-:a:g}}{eps}}then{agm{/{+:a:g}2}{sqrt{*:a:g}}}else:a}}}->agm{agm1{/1{sqrt2}}}->0.8472130847939792Multi-precisionversionusingthelib_BNlibrary{BN.DEC70}->70digits{defEPS{BN./1{BN.pow1045}}}->EPS{defAGM{lambda{:a:g}{if{={BN.compare{BN.abs{BN.-:a:g}}{EPS}}1}then{AGM{BN./{BN.+:a:g}2}{BN.sqrt{BN.*:a:g}}}else:a}}}->AGM{AGM1{BN./1{BN.sqrt2}}}->0.8472130847939790866064991234821916364814459103269421850605793726597339
(defunagm(ag)(agmag1.0e-15))(defunagm(agtol)(if(=<(-ag)tol)a(agm(next-aag)(next-gag)tol)))(defunnext-a(ag)(/(+ag)2))(defunnext-g(ag)(math:sqrt(*ag)))
Usage:
> (agm 1 (/ 1 (math:sqrt 2)))0.8472130847939792
function agm aa,g put abs(aa-g) into absdiff put (aa+g)/2 into aan put sqrt(aa*g) into gn repeat while abs(aan - gn) < absdiff put abs(aa-g) into absdiff put (aa+g)/2 into aan put sqrt(aa*g) into gn put aan into aa put gn into g end repeat return aaend agm
Example
put agm(1, 1/sqrt(2))-- ouput-- 0.847213
; This is not strictly LLVM, as it uses the C library function "printf".; LLVM does not provide a way to print values, so the alternative would be; to just load the string into memory, and that would be boring.; Additional comments have been inserted, as well as changes made from the output produced by clang such as putting more meaningful labels for the jumps$"ASSERTION"=comdatany$"OUTPUT"=comdatany@"ASSERTION"=linkonce_odrunnamed_addrconstant[48xi8]c"arithmetic-geometric mean undefined when x*y<0\0A\00",comdat,align1@"OUTPUT"=linkonce_odrunnamed_addrconstant[42xi8]c"The arithmetic-geometric mean is %0.19lf\0A\00",comdat,align1;--- The declarations for the external C functionsdeclarei32@printf(i8*,...)declarevoid@exit(i32)#1declaredouble@sqrt(double)#1declaredouble@llvm.fabs.f64(double)#2;----------------------------------------------------------------;-- arithmetic geometric meandefinedouble@agm(double,double)#0{%3=allocadouble,align8; allocate local g%4=allocadouble,align8; allocate local a%5=allocadouble,align8; allocate iota%6=allocadouble,align8; allocate a1%7=allocadouble,align8; allocate g1storedouble%1,double*%3,align8; store param g in local gstoredouble%0,double*%4,align8; store param a in local astoredouble1.000000e-15,double*%5,align8; store 1.0e-15 in iota (1.0e-16 was causing the program to hang)%8=loaddouble,double*%4,align8; load a%9=loaddouble,double*%3,align8; load g%10=fmuldouble%8,%9; a * g%11=fcmpoltdouble%10,0.000000e+00; a * g < 0.0bri1%11,label%enforce,label%loopenforce:%12=calli32(i8*,...)@printf(i8*getelementptrinbounds([48xi8],[48xi8]*@"ASSERTION",i320,i320))callvoid@exit(i321)#6unreachableloop:%13=loaddouble,double*%4,align8; load a%14=loaddouble,double*%3,align8; load g%15=fsubdouble%13,%14; a - g%16=calldouble@llvm.fabs.f64(double%15); fabs(a - g)%17=loaddouble,double*%5,align8; load iota%18=fcmpogtdouble%16,%17; fabs(a - g) > iotabri1%18,label%loop_body,label%eomloop_body:%19=loaddouble,double*%4,align8; load a%20=loaddouble,double*%3,align8; load g%21=fadddouble%19,%20; a + g%22=fdivdouble%21,2.000000e+00; (a + g) / 2.0storedouble%22,double*%6,align8; store %22 in a1%23=loaddouble,double*%4,align8; load a%24=loaddouble,double*%3,align8; load g%25=fmuldouble%23,%24; a * g%26=calldouble@sqrt(double%25)#4; sqrt(a * g)storedouble%26,double*%7,align8; store %26 in g1%27=loaddouble,double*%6,align8; load a1storedouble%27,double*%4,align8; store a1 in a%28=loaddouble,double*%7,align8; load g1storedouble%28,double*%3,align8; store g1 in gbrlabel%loopeom:%29=loaddouble,double*%4,align8; load aretdouble%29; return a};----------------------------------------------------------------;-- maindefinei32@main()#0{%1=allocadouble,align8; allocate x%2=allocadouble,align8; allocate ystoredouble1.000000e+00,double*%1,align8; store 1.0 in x%3=calldouble@sqrt(double2.000000e+00)#4; calculate the square root of two%4=fdivdouble1.000000e+00,%3; divide 1.0 by %3storedouble%4,double*%2,align8; store %4 in y%5=loaddouble,double*%2,align8; reload y%6=loaddouble,double*%1,align8; reload x%7=calldouble@agm(double%6,double%5); agm(x, y)%8=calli32(i8*,...)@printf(i8*getelementptrinbounds([42xi8],[42xi8]*@"OUTPUT",i320,i320),double%7)reti320; finished}attributes#0={noinlinenounwindoptnoneuwtable"correctly-rounded-divide-sqrt-fp-math"="false""disable-tail-calls"="false""less-precise-fpmad"="false""no-frame-pointer-elim"="false""no-infs-fp-math"="false""no-jump-tables"="false""no-nans-fp-math"="false""no-signed-zeros-fp-math"="false""no-trapping-math"="false""stack-protector-buffer-size"="8""target-cpu"="x86-64""target-features"="+fxsr,+mmx,+sse,+sse2,+x87""unsafe-fp-math"="false""use-soft-float"="false"}attributes#1={noreturn"correctly-rounded-divide-sqrt-fp-math"="false""disable-tail-calls"="false""less-precise-fpmad"="false""no-frame-pointer-elim"="false""no-infs-fp-math"="false""no-nans-fp-math"="false""no-signed-zeros-fp-math"="false""no-trapping-math"="false""stack-protector-buffer-size"="8""target-cpu"="x86-64""target-features"="+fxsr,+mmx,+sse,+sse2,+x87""unsafe-fp-math"="false""use-soft-float"="false"}attributes#2={nounwindreadnonespeculatable}attributes#4={nounwind}attributes#6={noreturn}
The arithmetic-geometric mean is 0.8472130847939791654
to about :a :b output and [:a - :b < 1e-15] [:a - :b > -1e-15]endto agm :arith :geom if about :arith :geom [output :arith] output agm (:arith + :geom)/2 sqrt (:arith * :geom)endshow agm 1 1/sqrt 2
functionagm(a,b,tolerance)ifnottoleranceortolerance<1e-15thentolerance=1e-15endrepeata,b=(a+b)/2,math.sqrt(a*b)untilmath.abs(a-b)<tolerancereturnaendprint(string.format("%.15f",agm(1,1/math.sqrt(2))))
Output:
0.847213084793979
Module Checkit { Function Agm { \\ new stack constructed at calling the Agm() with two values Repeat { Read a0, b0 Push Sqrt(a0*b0), (a0+b0)/2 ' last pushed first read } Until Stackitem(1)==Stackitem(2) =Stackitem(1) \\ stack deconstructed at exit of function } Print Agm(1,1/Sqrt(2))}CheckitMaple provides this function under the name GaussAGM. To compute a floating point approximation, use evalf.
>evalf(GaussAGM(1,1/sqrt(2)));# default precision is 10 digits0.8472130847>evalf[100](GaussAGM(1,1/sqrt(2)));# to 100 digits0.847213084793979086606499123482191636481445910326942185060579372659\7340048341347597232002939946112300
Alternatively, if one or both arguments is already a float, Maple will compute a floating point approximation automatically.
>GaussAGM(1.0,1/sqrt(2));0.8472130847
To any arbitrary precision, just increase PrecisionDigits
PrecisionDigits=85;AGMean[a_,b_]:=FixedPoint[{Tr@#/2,Sqrt[Times@@#]}&,N[{a,b},PrecisionDigits]]〚1〛
AGMean[1, 1/Sqrt[2]]0.8472130847939790866064991234821916364814459103269421850605793726597340048341347597232
function[a,g]=agm(a,g)%%arithmetic_geometric_mean(a,g)while(1)a0=a;a=(a0+g)/2;g=sqrt(a0*g);if(abs(a0-a)<a*eps)break;end;end;end
octave:26> agm(1,1/sqrt(2))ans = 0.84721
agm(a,b):=%pi/4*(a+b)/elliptic_kc(((a-b)/(a+b))^2)$agm(1,1/sqrt(2)),bfloat,fpprec:85;/* 8.472130847939790866064991234821916364814459103269421850605793726597340048341347597232b-1 */
П1<->П01ВП8/-/П2ИП0ИП1-ИП2-/-/x<031ИП1П3ИП0ИП1*КвКорП1ИП0ИП3+2/П0БП08ИП0С/П
MODULEAGM;FROMEXCEPTIONSIMPORTAllocateSource,ExceptionSource,GetMessage,RAISE;FROMLongConvIMPORTValueReal;FROMLongMathIMPORTsqrt;FROMLongStrIMPORTRealToStr;FROMTerminalIMPORTReadChar,Write,WriteString,WriteLn;VARTextWinExSrc:ExceptionSource;PROCEDUREReadReal():LONGREAL;VARbuffer:ARRAY[0..63]OFCHAR;i:CARDINAL;c:CHAR;BEGINi:=0;LOOPc:=ReadChar();IF((c>='0')AND(c<='9'))OR(c='.')THENbuffer[i]:=c;Write(c);INC(i)ELSEWriteLn;EXITENDEND;buffer[i]:=0C;RETURNValueReal(buffer)ENDReadReal;PROCEDUREWriteReal(r:LONGREAL);VARbuffer:ARRAY[0..63]OFCHAR;BEGINRealToStr(r,buffer);WriteString(buffer)ENDWriteReal;PROCEDUREAGM(a,g:LONGREAL):LONGREAL;CONSTiota=1.0E-16;VARa1,g1:LONGREAL;BEGINIFa*g<0.0THENRAISE(TextWinExSrc,0,"arithmetic-geometric mean undefined when x*y<0")END;WHILEABS(a-g)>iotaDOa1:=(a+g)/2.0;g1:=sqrt(a*g);a:=a1;g:=g1END;RETURNaENDAGM;VARx,y,z:LONGREAL;BEGINWriteString("Enter two numbers: ");x:=ReadReal();y:=ReadReal();WriteReal(AGM(x,y));WriteLnENDAGM.
Enter two numbers: 1.02.01.456791031046900
Enter two numbers: 1.00.7070.847154622368330
/* NetRexx */optionsreplaceformatcommentsjavacrossrefsymbolsnobinarynumericdigits18parsearga_g_.ifa_=''|a_='.'thena0=1elsea0=a_ifg_=''|g_='.'theng0=1/Math.sqrt(2)elseg0=g_sayagm(a0,g0)return--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~methodagm(a0,g0)publicstaticreturnsRexxa1=a0g1=g0loopwhile(a1-g1).abs()>=Math.pow(10,-14)temp=(a1+g1)/2g1=Math.sqrt(a1*g1)a1=tempendreturna1+0
Output:
0.8472130847939792
(define(a-nextag)(mul0.5(addag)))(define(g-nextag)(sqrt(mulag)))(define(amgagtolerance)(if(<=(subag)tolerance)a(amg(a-nextag)(g-nextag)tolerance)))(definequadrillionth0.000000000000001)(defineroot-reciprocal-2(div1.0(sqrt2.0)))(println"To the nearest one-quadrillionth, ""the arithmetic-geometric mean of ""1 and the reciprocal of the square root of 2 is "(amg1.0root-reciprocal-2quadrillionth))
importmathprocagm(a,g:float,delta:float=1.0e-15):float=varaNew:float=0aOld:float=agOld:float=gwhile(abs(aOld-gOld)>delta):aNew=0.5*(aOld+gOld)gOld=sqrt(aOld*gOld)aOld=aNewresult=aOldechoagm(1.0,1.0/sqrt(2.0))
Output:
8.4721308479397917e-01
See first 24 iterations:
frommathimportsqrtfromstrutilsimportparseFloat,formatFloat,ffDecimalprocagm(x,y:float):tuple[resA,resG:float]=vara,g:array[0..23,float]a[0]=xg[0]=yfornin1..23:a[n]=0.5*(a[n-1]+g[n-1])g[n]=sqrt(a[n-1]*g[n-1])(a[23],g[23])vart=agm(1,1/sqrt(2.0))echo("Result A: "&formatFloat(t.resA,ffDecimal,24))echo("Result G: "&formatFloat(t.resG,ffDecimal,24))
MODULEAgm;IMPORTMath:=LRealMath,Out;CONSTepsilon=1.0E-15;PROCEDUREOf*(a,g:LONGREAL):LONGREAL;VARna,ng,og:LONGREAL;BEGINna:=a;ng:=g;LOOPog:=ng;ng:=Math.sqrt(na*ng);na:=(na+og)*0.5;IFna-ng<=epsilonTHENEXITENDEND;RETURNng;ENDOf;BEGINOut.LongReal(Of(1,1/Math.sqrt(2)),0,0);Out.LnENDAgm.
8.4721308479397905E-1
class ArithmeticMean { function : Amg(a : Float, g : Float) ~ Nil { a1 := a; g1 := g; while((a1-g1)->Abs() >= Float->Power(10, -14)) { tmp := (a1+g1)/2.0; g1 := Float->SquareRoot(a1*g1); a1 := tmp; }; a1->PrintLine(); } function : Main(args : String[]) ~ Nil { Amg(1,1/Float->SquareRoot(2)); }}Output:
0.847213085
letrecagmagtol=iftol>abs_float(a-.g)thenaelseagm(0.5*.(a+.g))(sqrt(a*.g))tollet_=Printf.printf"%.16f\n"(agm1.0(sqrt0.5)1e-15)
Output
0.8472130847939792
: agm \ a b -- m while( 2dup <> ) [ 2dup + 2 / -rot * sqrt ] drop ;
Usage :
1 2 sqrt inv agm
0.847213084793979
importmath// import for sqrt() functionamean:func(x:Double,y:Double)->Double{(x+y)/2.}gmean:func(x:Double,y:Double)->Double{sqrt(x*y)}agm:func(a:Double,g:Double)->Double{while((a-g)abs()>pow(10,-12)){(a1,g1):=(amean(a,g),gmean(a,g))(a,g)=(a1,g1)}a}main:func{"%.16f"printfln(agm(1.,sqrt(0.5)))}
Output
0.8472130847939792
numericdigits20sayagm(1,1/rxcalcsqrt(2,16))::routineagmusestrictarga,gnumericdigits20a1=ag1=gloopwhileabs(a1-g1)>=1e-14temp=(a1+g1)/2g1=rxcalcsqrt(a1*g1,16)a1=tempendreturna1+0::requiresrxmathLIBRARY
0.8472130847939791968
Built-in:
agm(1,1/sqrt(2))
Iteration:
agm2(x,y)=if(x==y,x,agm2((x+y)/2,sqrt(x*y))
Port of the C example:
ProgramArithmeticGeometricMean;usesgmp;procedureagm(in1,in2:mpf_t;varout1,out2:mpf_t);beginmpf_add(out1,in1,in2);mpf_div_ui(out1,out1,2);mpf_mul(out2,in1,in2);mpf_sqrt(out2,out2);end;constnl=chr(13)+chr(10);varx0,y0,resA,resB:mpf_t;i:integer;beginmpf_set_default_prec(65568);mpf_init_set_ui(y0,1);mpf_init_set_d(x0,0.5);mpf_sqrt(x0,x0);mpf_init(resA);mpf_init(resB);fori:=0to6dobeginagm(x0,y0,resA,resB);agm(resA,resB,x0,y0);end;mp_printf('%.20000Ff'+nl,@x0);mp_printf('%.20000Ff'+nl+nl,@y0);end.
Output is as long as the C example.
functionagm(a,g:real;eps:real:=1e-10):real;beginvaran:=(a+g)/2;vargn:=Sqrt(a*g);whileAbs(an-gn)>epsdo(an,gn):=((an+gn)/2,Sqrt(an*gn));Result:=an;end;beginPrint(agm(1,1/Sqrt(2)))end.
0.847213084835193
#!/usr/bin/perl -wmy($a0,$g0,$a1,$g1);subagm($$){$a0=shift;$g0=shift;do{$a1=($a0+$g0)/2;$g1=sqrt($a0*$g0);$a0=($a1+$g1)/2;$g0=sqrt($a1*$g1);}while($a0!=$a1);return$a0;}printagm(1,1/sqrt(2))."\n";
Output:
0.847213084793979
functionagm(atoma,atomg,atomtolerance=1.0e-15)whileabs(a-g)>tolerancedo{a,g}={(a+g)/2,sqrt(a*g)}printf(1,"%0.15g\n",a)endwhilereturnaendfunction?agm(1,1/sqrt(2))-- (rounds to 10 d.p.)
0.8535533905932740.8472249029234940.8472130848351930.8472130847939790.8472130848
include ..\Utilitys.pmt1.0e-15 var tolerancedef test over over - abs tolerance >enddefdef agm /# n1 n2 -- n3 #/ test while over over + 2 / rot rot * sqrt test endwhileenddef1 1 2 sqrt / agm tostr ?
define('PRECISION',13);functionagm($a0,$g0,$tolerance=1e-10){// the bc extension deals in strings and cannot convert// floats in scientific notation by itself - hence// this manual conversion to a string$limit=number_format($tolerance,PRECISION,'.','');$an=$a0;$gn=$g0;do{list($an,$gn)=array(bcdiv(bcadd($an,$gn),2),bcsqrt(bcmul($an,$gn)),);}while(bccomp(bcsub($an,$gn),$limit)>0);return$an;}bcscale(PRECISION);echoagm(1,1/bcsqrt(2));
0.8472130848350
main => println(agm(1.0, 1/sqrt(2))).agm(A,G) = A, A-G < 1.0e-10 => true.agm(A,G) = agm((A+G)/2, sqrt(A*G)).
0.847213084835193
(scl 80)(de agm (A G) (do 7 (prog1 (/ (+ A G) 2) (setq G (sqrt A G) A @) ) ) )(round (agm 1.0 (*/ 1.0 1.0 (sqrt 2.0 1.0))) 70 )
Output:
-> "0.8472130847939790866064991234821916364814459103269421850605793726597340"
arithmetic_geometric_mean: /* 31 August 2012 */ procedure options (main); declare (a, g, t) float (18); a = 1; g = 1/sqrt(2.0q0); put skip list ('The arithmetic-geometric mean of ' || a || ' and ' || g || ':'); do until (abs(a-g) < 1e-15*a); t = (a + g)/2; g = sqrt(a*g); a = t; put skip data (a, g); end; put skip list ('The result is:', a);end arithmetic_geometric_mean;Results:
The arithmetic-geometric mean of 1.00000000000000000E+0000 and 7.07106781186547524E-0001: A= 8.53553390593273762E-0001 G= 8.40896415253714543E-0001;A= 8.47224902923494153E-0001 G= 8.47201266746891460E-0001;A= 8.47213084835192807E-0001 G= 8.47213084752765367E-0001;A= 8.47213084793979087E-0001 G= 8.47213084793979087E-0001;The result is: 8.47213084793979087E-0001
$defineEPS=1e-14localfunctionagm(a,g)whilemath.abs(a-g)>math.abs(a)*EPSdoa,g=(a+g)/2,math.sqrt(a*g)endreturnaendprint(agm(1.0,1.0/math.sqrt(2)))
0.84721308479398
Input values should be floating point
sqrt = (x) : xi = 1 7 times : xi = (xi + x / xi) / 2 . xi.agm = (x, y) : 7 times : a = (x + y) / 2 g = sqrt(x * y) x = a y = g . x.
functionagm([Double]$a,[Double]$g){[Double]$eps=1E-15[Double]$a1=[Double]$g1=0while([Math]::Abs($a-$g)-gt$eps){$a1,$g1=$a,$g$a=($a1+$g1)/2$g=[Math]::Sqrt($a1*$g1)}[pscustomobject]@{a="$a"g="$g"}}agm1(1/[Math]::Sqrt(2))
Output:
a g - - 0.847213084793979 0.847213084793979
agm(A,G,A):-abs(A-G)<1.0e-15,!.agm(A,G,Res):-A1is(A+G)/2.0,G1issqrt(A*G),!,agm(A1,G1,Res).?-agm(1,1/sqrt(2),Res).Res=0.8472130847939792.
The calculation generates two new values from two existing values which is the classic example for the use ofassignment to a list of values in the one statement, so ensuring an gn are only calculated from an-1 gn-1.
frommathimportsqrtdefagm(a0,g0,tolerance=1e-10):""" Calculating the arithmetic-geometric mean of two numbers a0, g0. tolerance the tolerance for the converged value of the arithmetic-geometric mean (default value = 1e-10) """an,gn=(a0+g0)/2.0,sqrt(a0*g0)whileabs(an-gn)>tolerance:an,gn=(an+gn)/2.0,sqrt(an*gn)returnanprintagm(1,1/sqrt(2))
0.847213084835
from decimal import Decimal, getcontextdef agm(a, g, tolerance=Decimal("1e-65")): while True: a, g = (a + g) / 2, (a * g).sqrt() if abs(a - g) < tolerance: return agetcontext().prec = 70print agm(Decimal(1), 1 / Decimal(2).sqrt())0.847213084793979086606499123482191636481445910326942185060579372659734
All the digits shown are correct.
[ $ "bigrat.qky" loadfile ] now! [ temp put [ 2over 2over temp share approx= iff 2drop done 2over 2over v* temp share vsqrt drop dip [ dip [ v+ 2 n->v v/ ] ] again ] base share temp take ** round ] is agm ( n/d n/d n --> n/d ) 1 n->v 2 n->v 125 vsqrt drop 1/v 125 agm 2dup 125 point$ echo$ cr cr swap say "Num: " echo cr say "Den: " echo
Rational approximation good to 125 decimal places.
0.84721308479397908660649912348219163648144591032694218506057937265973400483413475972320029399461122994212228562523341096309796Num: 25070388762104643854110087231213532104992429267859552974434367463980830062627660152123462048041692668477424160883635235463565Den: 29591597689029002472001305353032599592592702596663142670993392754036951453351898973702304260474345315746065192782388085181246
arithmeticMean <- function(a, b) { (a + b)/2 }geometricMean <- function(a, b) { sqrt(a * b) }arithmeticGeometricMean <- function(a, b) { rel_error <- abs(a - b) / pmax(a, b) if (all(rel_error < .Machine$double.eps, na.rm=TRUE)) { agm <- a return(data.frame(agm, rel_error)); } Recall(arithmeticMean(a, b), geometricMean(a, b)) }agm <- arithmeticGeometricMean(1, 1/sqrt(2))print(format(agm, digits=16))agm rel_error1 0.8472130847939792 1.310441309927519e-16
This function also works on vectors a and b (following the spirit of R):
a <- c(1, 1, 1)b <- c(1/sqrt(2), 1/sqrt(3), 1/2)agm <- arithmeticGeometricMean(a, b)print(format(agm, digits=16))
agm rel_error1 0.8472130847939792 1.310441309927519e-162 0.7741882646460426 0.000000000000000e+003 0.7283955155234534 0.000000000000000e+00
This version uses Racket's normal numbers:
#lang racket(define (agm a g [ε 1e-15]) (if (<= (- a g) ε) a (agm (/ (+ a g) 2) (sqrt (* a g)) ε)))(agm 1 (/ 1 (sqrt 2)))
Output:
0.8472130847939792
This alternative version uses arbitrary precision floats:
#lang racket(require math/bigfloat)(bf-precision 200)(bfagm 1.bf (bf/ (bfsqrt 2.bf)))
Output:
(bf #e0.84721308479397908660649912348219163648144591032694218506057918)
(formerly Perl 6)
sub agm( $a is copy, $g is copy ) { ($a, $g) = ($a + $g)/2, sqrt $a * $g until $a ≅ $g; return $a;} say agm 1, 1/sqrt 2;0.84721308479397917
It's also possible to write it recursively:
sub agm( $a, $g ) { $a ≅ $g ?? $a !! agm(|@$_) given ($a + $g)/2, sqrt $a * $g;}say agm 1, 1/sqrt 2;We can also get a bit fancy and use a converging sequence of complex numbers:
sub agm { ($^z, {(.re+.im)/2 + (.re*.im).sqrt*1i} ... * ≅ *) .tail.re} say agm 1 + 1i/2.sqrtdefine agm use $a, $g, $errlim # $errlim $g $a "%d %g %d\n" print $a 1.0 + as $t repeat $a 1.0 * $g - abs -15 exp10 $a * > while $a $g + 2 / as $t $a $g * sqrt as $g $t as $a $g $a $t "t: %g a: %g g: %g\n" print $a16 1 2 sqrt / 1 agm "agm: %.15g\n" print
t: 0.853553 a: 0.853553 g: 0.840896t: 0.847225 a: 0.847225 g: 0.847201t: 0.847213 a: 0.847213 g: 0.847213t: 0.847213 a: 0.847213 g: 0.847213agm: 0.847213084793979
function agm(x,y)set a = xset g = ywhile abs(a - g) > 0.00000000001set an = (a + g)/2set gn = sqrt(a * g)set a = anset g = gnset i = i + 1end whileset result = gend functionset x = 1set y = 1/sqrt(2)echo (x + y)/2echo sqrt(x+y)echo agm(x,y)
0.8535533910.8408964150.847213085
Also, this version of the AGM REXX program has three short circuits within it for an equality case and for two zero cases.
REXX supports arbitrary precision, so the default digits can be changed if desired.
/*REXX program calculates the AGM (arithmetic─geometric mean) of two (real) numbers. */parse arg a b digs . /*obtain optional numbers from the C.L.*/if digs=='' | digs=="," then digs= 120 /*No DIGS specified? Then use default.*/numeric digits digs /*REXX will use lots of decimal digits.*/if a=='' | a=="," then a= 1 /*No A specified? Then use the default*/if b=='' | b=="," then b= 1 / sqrt(2) /* " B " " " " " */call AGM a,b /*invoke the AGM function. */say '1st # =' a /*display the A value. */say '2nd # =' b /* " " B " */say ' AGM =' agm(a, b) /* " " AGM " */exit 0 /*stick a fork in it, we're all done. *//*──────────────────────────────────────────────────────────────────────────────────────*/agm: procedure: parse arg x,y; if x=y then return x /*is this an equality case?*/ if y=0 then return 0 /*is Y equal to zero ? */ if x=0 then return y/2 /* " X " " " */ d= digits() /*obtain the current decimal digits. */ numeric digits d + 5 /*add 5 more digs to ensure convergence*/ tiny= '1e-' || (digits() - 1) /*construct a pretty tiny REXX number. */ ox= x + 1 /*ensure that the old X ¬= new X. */ do while ox\=x & abs(ox)>tiny /*compute until the old X ≡ new X. */ ox= x; oy= y /*save the old value of X and Y. */ x= (ox + oy) * .5 /*compute " new " " X. */ y= sqrt(ox * oy) /* " " " " " Y. */ end /*while*/ numeric digits d /*restore the original decimal digits. */ return x / 1 /*normalize X to new " " *//*──────────────────────────────────────────────────────────────────────────────────────*/sqrt: procedure; parse arg x; if x=0 then return 0; d=digits(); m.=9; numeric form; h=d+6 numeric digits; parse value format(x,2,1,,0) 'E0' with g 'E' _ .; g=g *.5'e'_ % 2 do j=0 while h>9; m.j=h; h=h % 2 + 1; end /*j*/ do k=j+5 to 0 by -1; numeric digits m.k; g=(g+x/g)*.5; end /*k*/; return g
1st # = 12nd # = 0.707106781186547524400844362104849039284835937688474036588339868995366239231053519425193767163820786367506923115456148513 AGM = 0.847213084793979086606499123482191636481445910326942185060579372659734004834134759723200293994611229942122285625233410963
decimals(9)see agm(1, 1/sqrt(2)) + nlsee agm(1,1/pow(2,0.5)) + nlfunc agm agm,g while agm an = (agm + g)/2 gn = sqrt(agm*g) if fabs(agm-g) <= fabs(an-gn) exit ok agm = an g = gn end return gn
≪ 1E-10 → epsilon ≪WHILE DUP2 - ABS epsilon >REPEAT DUP2 + 2 / ROT ROT * √END DROP≫ ≫ ‘AGM’ STO
1 2 / √ AGM
1: .847213084835
The thing to note about this implementation is that it uses theFlt library for high-precision math. This lets you adapt context (including precision and epsilon) to a ridiculous-in-real-life degree.
# The flt package (http://flt.rubyforge.org/) is useful for high-precision floating-point math.# It lets us control 'context' of numbers, individually or collectively -- including precision# (which adjusts the context's value of epsilon accordingly).require 'flt'include FltBinNum.Context.precision = 512 # default 53 (bits)def agm(a,g) new_a = BinNum a new_g = BinNum g while new_a - new_g > new_a.class.Context.epsilon do old_g = new_g new_g = (new_a * new_g).sqrt new_a = (old_g + new_a) * 0.5 end new_gendputs agm(1, 1 / BinNum(2).sqrt)
0.84721308479397908660649912348219163648144591032694218506057937265973400483413475972320029399461122994212228562523341096309796266583087105969971363598338426
Adjusting the precision setting (at about line 9) will of course affect this. :-)
Ruby has a BigDecimal class in standard library
require 'bigdecimal'PRECISION = 100EPSILON = 0.1 ** (PRECISION/2)BigDecimal::limit(PRECISION)def agm(a,g) while a - g > EPSILON a, g = (a+g)/2, (a*g).sqrt(PRECISION) end [a, g]enda = BigDecimal(1)g = 1 / BigDecimal(2).sqrt(PRECISION)puts agm(a, g)
0.847213084793979086606499123482191636481445910326942185060579372659734004834134759723201915677745718E00.8472130847939790866064991234821916364814459103269421850605793726597340048341347597231986723114767413E0
// Accepts two command line arguments// cargo run --name agm arg1 arg2fn main () { let mut args = std::env::args(); let x = args.nth(1).expect("First argument not specified.").parse::<f32>().unwrap(); let y = args.next().expect("Second argument not specified.").parse::<f32>().unwrap(); let result = agm(x,y); println!("The arithmetic-geometric mean is {}", result);}fn agm (x: f32, y: f32) -> f32 { let e: f32 = 0.000001; let mut a = x; let mut g = y; let mut a1: f32; let mut g1: f32; if a * g < 0f32 { panic!("The arithmetric-geometric mean is undefined for numbers less than zero!"); } else { loop { a1 = (a + g) / 2.; g1 = (a * g).sqrt(); a = a1; g = g1; if (a - g).abs() < e { return a; } } }}Output of running with arguments 1, 0.70710678:
The arithmetic-geometric mean is 1.456791
def agm(a: Double, g: Double, eps: Double): Double = { if (math.abs(a - g) < eps) (a + g) / 2 else agm((a + g) / 2, math.sqrt(a * g), eps) } agm(1, math.sqrt(2)/2, 1e-15)(define agm (case-lambda ((a0 g0) ; call again with default value for tolerance (agm a0 g0 1e-8)) ((a0 g0 tolerance) ; called with three arguments (do ((a a0 (* (+ a g) 1/2)) (g g0 (sqrt (* a g)))) ((< (abs (- a g)) tolerance) a)))))(display (agm 1 (/ 1 (sqrt 2)))) (newline)
0.8472130848351929
$ include "seed7_05.s7i"; include "float.s7i"; include "math.s7i";const func float: agm (in var float: a, in var float: g) is func result var float: agm is 0.0; local const float: iota is 1.0E-7; var float: a1 is 0.0; var float: g1 is 0.0; begin if a * g < 0.0 then raise RANGE_ERROR; else while abs(a - g) > iota do a1 := (a + g) / 2.0; g1 := sqrt(a * g); a := a1; g := g1; end while; agm := a; end if; end func; const proc: main is func begin writeln(agm(1.0, 2.0) digits 6); writeln(agm(1.0, 1.0 / sqrt(2.0)) digits 6); end func;
1.4567910.847213
import <Utilities/Math.sl>;agm(a, g) := let iota := 1.0e-15; arithmeticMean := 0.5 * (a + g); geometricMean := sqrt(a * g); in a when abs(a-g) < iota else agm(arithmeticMean, geometricMean);main := agm(1.0, 1.0 / sqrt(2));
0.847213
func agm(a, g) { loop { var (a1, g1) = ((a+g)/2, sqrt(a*g)) [a1,g1] == [a,g] && return a (a, g) = (a1, g1) }}say agm(1, 1/sqrt(2))0.8472130847939790866064991234821916364814
That is simply a copy/paste of the already existing agm method in the Number class:
agm:y "return the arithmetic-geometric mean agm(x, y) of the receiver (x) and the argument, y. See https://en.wikipedia.org/wiki/Arithmetic-geometric_mean" |ai an gi gn epsilon delta| ai := (self + y) / 2. gi := (self * y) sqrt. epsilon := self ulp. [ an := (ai + gi) / 2. gn := (ai * gi) sqrt. delta := (an - ai) abs. ai := an. gi := gn. ] doUntil:[ delta < epsilon ]. ^ ai
Transcript showCR: (24 agm:6).Transcript showCR: ( (1/2) agm:(1/6) ).Transcript showCR: (1 agm:(1 / 2 sqrt)).
13.45817148172560.3106027972074830.847213084793979
The solution uses recursive WITH clause (aka recursive CTE, recursive query, recursive factored subquery). Some, perhaps many, but not all SQL dialects support recursive WITH clause. The solution below was written and tested in Oracle SQL - Oracle has supported recursive WITH clause since version 11.2.
with rec (rn, a, g, diff) as ( select 1, 1, 1/sqrt(2), 1 - 1/sqrt(2) from dual union all select rn + 1, (a + g)/2, sqrt(a * g), (a + g)/2 - sqrt(a * g) from rec where diff > 1e-38 )select *from recwhere diff <= 1e-38;
RN A G DIFF-- ----------------------------------------- ------------------------------------------ ------------------------------------------ 6 0.847213084793979086606499123482191636480 0.8472130847939790866064991234821916364792 0.0000000000000000000000000000000000000008
fun agm(a, g) = let fun agm'(a, g, eps) = if Real.abs(a-g) < eps then a else agm'((a+g)/2.0, Math.sqrt(a*g), eps) in agm'(a, g, 1e~15) end;
agm(1.0, 1.0/Math.sqrt(2.0)) => 0.847213084794
mata real scalar agm(real scalar a, real scalar b) {real scalar cdo {c=0.5*(a+b)b=sqrt(a*b)a=c} while (a-b>1e-15*a)return(0.5*(a+b))}agm(1,1/sqrt(2))end.8472130848
import Darwinenum AGRError : Error {case undefined}func agm(_ a: Double, _ g: Double, _ iota: Double = 1e-8) throws -> Double {var a = avar g = gvar a1: Double = 0var g1: Double = 0guard a * g >= 0 else {throw AGRError.undefined}while abs(a - g) > iota {a1 = (a + g) / 2g1 = sqrt(a * g)a = a1g = g1}return a}do {try print(agm(1, 1 / sqrt(2)))} catch {print("agr is undefined when a * g < 0")}0.847213084835193
The tricky thing about this implementation is that despite the finite precision available to IEEE doubles (which Tcl uses in its implementation of floating point arithmetic, in common with many other languages) the sequence of values does notquite converge to a single value; it gets to within a ULP and then errors prevent it from getting closer. This means that an additional termination condition is required: once a value does not change (hence theold_b variable) we have got as close as we can. Note also that we are using exact equality with floating point; this is reasonable because this is a rapidly converging sequence (it only takes 4 iterations in this case).
proc agm {a b} { set old_b [expr {$b<0?inf:-inf}] while {$a != $b && $b != $old_b} {set old_b $blassign [list [expr {0.5*($a+$b)}] [expr {sqrt($a*$b)}]] a b } return $a}puts [agm 1 [expr 1/sqrt(2)]]Output:
0.8472130847939792
| Display | Key | Display | Key | Display | Key | Display | Key |
|---|---|---|---|---|---|---|---|
| 00 33 | STO | 25 03 | 3 | 50 | 75 | ||
| 01 02 | 2 | 26 12 | INV | 51 | 76 | ||
| 02 32 | x<>t | 27 44 | EE | 52 | 77 | ||
| 03 64 | × | 28 41 | R/S | 53 | 78 | ||
| 04 32 | x<>t | 29 | 54 | 79 | |||
| 05 94 | = | 30 | 55 | 80 | |||
| 06 48 | *√x | 31 | 56 | 81 | |||
| 07 32 | x<>t | 32 | 57 | 82 | |||
| 08 84 | + | 33 | 58 | 83 | |||
| 09 34 | RCL | 34 | 59 | 84 | |||
| 10 02 | 2 | 35 | 60 | 85 | |||
| 11 94 | = | 36 | 61 | 86 | |||
| 12 54 | ÷ | 37 | 62 | 87 | |||
| 13 02 | 2 | 38 | 63 | 88 | |||
| 14 94 | = | 39 | 64 | 89 | |||
| 15 33 | STO | 40 | 65 | 90 | |||
| 16 02 | 2 | 41 | 66 | 91 | |||
| 17 44 | EE | 42 | 67 | 92 | |||
| 18 94 | = | 43 | 68 | 93 | |||
| 19 32 | x<>t | 44 | 69 | 94 | |||
| 20 44 | EE | 45 | 70 | 95 | |||
| 21 94 | = | 46 | 71 | 96 | |||
| 22 12 | INV | 47 | 72 | 97 | |||
| 23 37 | *x=t | 48 | 73 | 98 | |||
| 24 00 | 0 | 49 | 74 | 99 |
Asterisk denotes 2nd function key.
| 0: Unused | 1: Unused | 2: Previous Term | 3: Unused | 4: Unused |
| 5: Unused | 6: Unused | 7: Unused | 8: Unused | 9: Unused |
Annotated listing:
STO 2 x<>t // x := term a, t := R2 := term g× x<>t = √x // Calculate term g'x<>t + RCL 2 = / 2 = STO 2 // Calculate term a'EE = x<>t EE = // Round terms to ten digitsINV x=t 0 3 // Loop if unequalINV EE // Exit scientific notationR/S // End
Usage:
Enter term a, press x<>t, then enter term g. Finally, press RST R/S to run the program.
1 x<>t 2 √x 1/x RST R/S
.8472130848
# Calculate the arithmetic-geometric meanAgm ← ⊙◌◌⍢(⊃(√×|÷2+)|<⌵-)Agm 1 ÷:1√2 0.0000001
0.8472130848351929
ksh is one of the few unix shells that can do floating point arithmetic (bash does not).
function agm { float a=$1 g=$2 eps=${3:-1e-11} tmp while (( abs(a-g) > eps )); do print "debug: a=$a\tg=$g" tmp=$(( (a+g)/2.0 )) g=$(( sqrt(a*g) )) a=$tmp done echo $a}agm $((1/sqrt(2))) 1debug: a=0.7071067812g=1debug: a=0.8535533906g=0.8408964153debug: a=0.8472249029g=0.8472012668debug: a=0.8472130848g=0.8472130847debug: a=0.8472130848g=0.8472130848debug: a=0.8472130848g=0.84721308480.8472130848
You can get a more approximate convergence by changing the while condition to compare the numbers as strings: change
while (( abs(a-g) > eps ))
to
while [[ $a != $g ]]
import math const ep = 1e-14 fn agm(aa f64, gg f64) f64 { mut a, mut g := aa, gg for math.abs(a-g) > math.abs(a)*ep { t := a a, g = (a+g)*.5, math.sqrt(t*g) } return a} fn main() { println(agm(1.0, 1.0/math.sqrt2))}Using standard math module
import math.statsimport mathfn main() { println(stats.geometric_mean<f64>([1.0, 1.0/math.sqrt2]))}0.8408964152537145
var eps = 1e-14var agm = Fn.new { |a, g| while ((a-g).abs > a.abs * eps) { var t = a a = (a+g)/2 g = (t*g).sqrt } return a}System.print(agm.call(1, 1/2.sqrt))0.84721308479398
include c:\cxpl\codesi;real A, A1, G;[Format(0, 16);A:= 1.0; G:= 1.0/sqrt(2.0);repeatA1:= (A+G)/2.0;G:= sqrt(A*G);A:= A1;RlOut(0, A); RlOut(0, G); RlOut(0, A-G); CrLf(0);untilA=G;]
Output:
8.5355339059327400E-001 8.4089641525371500E-001 1.2656975339559100E-002 8.4722490292349400E-001 8.4720126674689100E-001 2.3636176602726000E-005 8.4721308483519300E-001 8.4721308475276500E-001 8.2427509262572600E-011 8.4721308479397900E-001 8.4721308479397900E-001 0.0000000000000000E+000
a:=1.0; g:=1.0/(2.0).sqrt();while(not a.closeTo(g,1.0e-15)){ a1:=(a+g)/2.0; g=(a*g).sqrt(); a=a1; println(a," ",g," ",a-g);}0.853553 0.840896 0.0126570.847225 0.847201 2.36362e-050.847213 0.847213 8.24275e-110.847213 0.847213 1.11022e-16
Or, using tail recursion
fcn(a=1.0, g=1.0/(2.0).sqrt()){ println(a," ",g," ",a-g); if(a.closeTo(g,1.0e-15)) return(a) else return(self.fcn((a+g)/2.0, (a*g).sqrt()));}()1 0.707107 0.2928930.853553 0.840896 0.0126570.847225 0.847201 2.36362e-050.847213 0.847213 8.24275e-110.847213 0.847213 1.11022e-16