Euler's constant 0.5772...
You are encouraged to solve this task according to the task description, using any language you may know.
- Task.
Compute the Euler constant 0.5772...
Discovered by Leonhard Euler around 1730, it is the most ubiquitous mathematical constant after pi and e, but appears more arcane than these.
Denoted gamma (γ), it measures the amount by which the partial sums of the harmonic series (the simplest diverging series) differ from the logarithmic function (its approximating integral): lim n → ∞ (1 + 1/2 + 1/3 + … + 1/n − log(n)).
The definition of γ converges too slowly to be numerically useful, but in 1735 Euler himself applied his recently discovered summation formula to compute ‘the notable number’ accurate to 15 places. For a single-precision implementation this is still the most economic algorithm.
In 1961, the young Donald Knuth used Euler's method to evaluate γ to 1271 places. Knuth found that the computation of the Bernoulli numbers required in the Euler-Maclaurin formula was the most time-consuming part of the procedure.
The next year Dura Sweeney computed 3566 places, using a formula based on the expansion of the exponential integral which didn't need Bernoulli numbers. It's a bit-hungry method though: 2d digits of working precision obtain d correct places only.
This was remedied in 1988 by David Bailey; meanwhile Richard Brent and Ed McMillan had published an even more efficient algorithm based on Bessel function identities and found 30100 places in 20 hours time.
Nowadays the old records have far been exceeded: over 6·1011 decimal places are already known. These massive computations suggest that γ is neither rational nor algebraic, but this is yet to be proven.
- References.
[1] Gourdon and Sebah, The Euler constant γ. (for all formulas)
[2] Euler's original journal article translated from the latin (p. 9)
Ada
Three solutions here: the Vacca series, then two useful approximations for generally-used Ada types Float and Long_Float.
with Ada.Numerics.Elementary_Functions; use Ada.Numerics.Elementary_Functions;
with Ada.Numerics.Long_Elementary_Functions; use Ada.Numerics.Long_Elementary_Functions;
with Ada.Text_IO; use Ada.Text_IO;
procedure Eulers_Constant is
function Euler_Vacca (Iterations : Integer) return Long_Float is
Gamma : Long_Float := 1.0;
Term : Long_Float;
Power : Long_Integer;
Sign : Long_Float;
begin
Gamma := 0.5 - (1.0 / 3.0);
for I in 2 .. Iterations loop
Power := 2 ** Natural (I);
Sign := -1.0;
Term := 0.0;
for Domin in Power .. (2 * Power - 1) loop
Sign := - (Sign);
Term := Term + Sign / Long_Float (Domin);
end loop;
Gamma := Gamma + (Long_Float (I) * Term);
end loop;
return Gamma;
end Euler_Vacca;
-- Ada Float type is IEEE 754 32-bit, giving 9 decimal digits of precision
Euler_Castellanos_Float : constant Float :=
(((80.0 ** 3) + 92.0) /
(61.0 ** 4)) ** (1.0 / 6.0);
-- Ada Long_Float type is IEEE 754 32-bit, giving 14 decimal digits of precision
Euler_Castellanos_Long_Float : constant Long_Float :=
(990.0 ** 3 - 55.0 ** 3 - 79.0 ** 2 - 16.0) /
70.0 ** 5;
Iters : Integer;
begin
Put_Line ("Its. Vacca");
Iters := 2;
while Iters <= 32 loop
Put_Line (Iters'Image & " " & Euler_Vacca (Iters)'Image);
Iters := Iters + 2;
end loop;
Put_Line ("Castellanos approximation for standard Float (9 digits): " & Euler_Castellanos_Float'Image);
Put_Line ("Castellanos approximation for Long Float (14 digits): " & Euler_Castellanos_Long_Float'Image);
end Eulers_Constant;
- Output:
Its. Vacca 2 3.14285714285714E-01 4 4.82164184398886E-01 6 5.45853770405349E-01 8 5.67441138957738E-01 10 5.74285301882304E-01 12 5.76361123043496E-01 14 5.76971520706463E-01 16 5.77147000098518E-01 18 5.77196591397621E-01 20 5.77210419691580E-01 22 5.77214234389975E-01 24 5.77215277471336E-01 26 5.77215560593404E-01 28 5.77215636961856E-01 30 5.77215657450952E-01 32 5.77215662922473E-01 Castellanos approximation for standard Float (9 digits): 5.77216E-01 Castellanos approximation for Long Float (14 digits): 5.77215664901529E-01
ALGOL W
begin % calculate Euler's constant, translated from the XPL0 sample %
% which is translated from the C sample %
long real A, B, H, N2, R, U, V;
long real array S ( 0 :: 1 );
long real array B2( 0 :: 9 );
long real Epsilon;
integer K, K2, M, N;
Epsilon := 1'-6;
% set output format %
i_w := 1; s_w := 0; r_w := 18; r_d := 15; r_format := "A";
write( "From the definition, error 3e-10" );
N := 400; H := 1.0;
for K1 := 2 until N do H := H + 1.0 / K1;
comment Faster convergence: Negoi, 1997 ;
A := Ln( N + 0.5 + 1.0/( 24.0 * N ) );
write( "Hn ", H );
write( "gamma ", H - A ); write( "K = ", N ); write();
write( "Sweeney, 1963, error 3e-10" );
N := 21; S( 0 ) := 0; S( 1 ) := N;
R := N; K:= 1;
while begin K := K + 1;
R := R * N / K;
S( K rem 2 ) := S( K rem 2 ) + R / K;
R > Epsilon
end
do begin end;
write( "gamma ", S( 1 ) - S( 0 ) - ln( N ) );write( "K = ", K ); write();
write( "Bailey, 1988" );
N := 5; A := 1; H := 1;
N2 := 2 ** N;
R := 1; K := 1;
while begin K := K + 1;
R := R * N2 / K;
H := H + 1 / K;
B := A; A := A + R * H;
abs( B - A ) > Epsilon
end
do begin end;
A := A * N2 / Exp(N2);
write( "gamma ", A - N * Ln( 2 ) ); write( "K = ", K ); write();
write( "Brent-McMillan, 1980" );
N := 13; A := -Ln( N );
B := 1; U := A; V := B;
N2 := N * N; K2 := 0; K := 0;
while begin K2 := K2 + 2 * K + 1;
K := K + 1;
A := A * N2 / K;
B := B * N2 / K2;
A := ( A + B ) / K;
U := U + A;
V := V + B;
abs( A ) > Epsilon
end
do begin end;
write( "gamma ", U / V ); write( "K = ", K ); write();
write( "How Euler did it in 1735" );
comment Bernoulli numbers with even indices;
B2( 0 ) := 1; B2( 1 ) := 1 / 6; B2( 2 ) := -1 / 30;
B2( 3 ) := 1 / 42; B2( 4 ) := -1 / 30; B2( 5 ) := 5 / 66;
B2( 6 ) := -691 / 2730; B2( 7 ) := 7 / 6; B2( 8 ) := -3617 / 510;
B2( 9 ) := 43867 / 98;
M := 7; N := 10;
comment Nth harmonic number;
H := 1;
for K1 := 2 until N do H := H + 1 / K1;
write( "Hn ", H );
H := H - Ln( N );
write( " -ln ", H );
comment Expansion C:= -digamma(1);
A := -1 / ( 2 * N );
N2 := N * N;
R := 1;
for K1 := 1 until M do begin
R := R * N2;
A := A + B2( K1 ) / (2 * K1 * R )
end for_K1;
write( "err ", A ); write( "gamma ", H + A ); write( "K = ", N + M );
write();
write( "C = 0.57721566490153286..." ); write()
end.
- Output:
From the definition, error 3e-10 Hn 6.569929691176506 gamma 0.577215664576573 K = 400 Sweeney, 1963, error 3e-10 gamma 0.577215664563631 K = 68 Bailey, 1988 gamma 0.577215664901535 K = 89 Brent-McMillan, 1980 gamma 0.577215664901533 K = 40 How Euler did it in 1735 Hn 2.928968253968254 -ln 0.626383160974208 err -0.049167496072675 gamma 0.577215664901533 K = 17 C = 0.57721566490153286...
BASIC
FreeBASIC
Single precision
'**********************************************
'Subject: Comparing five methods for
' computing Euler's constant 0.5772...
'tested : FreeBasic 1.08.1
'----------------------------------------------
const eps = 1e-6
dim as double a, b, h, n2, r, u, v
dim as integer k, k2, m, n
? "From the definition, err. 3e-10"
n = 400
h = 1
for k = 2 to n
h += 1 / k
next k
'faster convergence: Negoi, 1997
a = log(n +.5 + 1 / (24*n))
? "Hn "; h
? "gamma"; h - a; !"\nk ="; n
?
? "Sweeney, 1963, err. idem"
n = 21
dim as double s(1) = {0, n}
r = n
k = 1
do
k += 1
r *= n / k
s(k and 1) += r / k
loop until r < eps
? "gamma"; s(1) - s(0) - log(n); !"\nk ="; k
?
? "Bailey, 1988"
n = 5
a = 1
h = 1
n2 = 2^n
r = 1
k = 1
do
k += 1
r *= n2 / k
h += 1 / k
b = a: a += r * h
loop until abs(b - a) < eps
a *= n2 / exp(n2)
? "gamma"; a - n * log(2); !"\nk ="; k
?
? "Brent-McMillan, 1980"
n = 13
a = -log(n)
b = 1
u = a
v = b
n2 = n * n
k2 = 0
k = 0
do
k2 += 2*k + 1
k += 1
a *= n2 / k
b *= n2 / k2
a = (a + b) / k
u += a
v += b
loop until abs(a) < eps
? "gamma"; u / v; !"\nk ="; k
?
? "How Euler did it in 1735"
'Bernoulli numbers with even indices
dim as double B2(9) = {1,1/6,-1/30,1/42,_
-1/30,5/66,-691/2730,7/6,-3617/510,43867/798}
m = 7
if m > 9 then end
n = 10
'n-th harmonic number
h = 1
for k = 2 to n
h += 1 / k
next k
? "Hn "; h
h -= log(n)
? " -ln"; h
'expansion C = -digamma(1)
a = -1 / (2*n)
n2 = n * n
r = 1
for k = 1 to m
r *= n2
a += B2(k) / (2*k * r)
next k
? "err "; a; !"\ngamma"; h + a; !"\nk ="; n + m
?
? "C = 0.57721566490153286..."
end
- output:
From the definition, err. 3e-10 Hn 6.569929691176506 gamma 0.5772156645765731 k = 400 Sweeney, 1963, err. idem gamma 0.5772156645636311 k = 68 Bailey, 1988 gamma 0.5772156649015341 k = 89 Brent-McMillan, 1980 gamma 0.5772156649015329 k = 40 How Euler did it in 1735 Hn 2.928968253968254 -ln 0.6263831609742079 err -0.04916749607267539 gamma 0.5772156649015325 k = 17 C = 0.57721566490153286...
Multi precision
From first principles
'***************************************************
'Subject: Computation of Euler's constant 0.5772...
' with the Brent-McMillan algorithm B1,
' Math. Comp. 34 (1980), 305-312
'tested : FreeBasic 1.08.1 with gmp 6.2.0
'---------------------------------------------------
#include "gmp.bi"
'multi-precision float pointers
Dim as mpf_ptr a, b
Dim shared as mpf_ptr k2, u, v
'unsigned long integers
Dim as ulong k, n, n2, r, s, t
'precision parameters
Dim shared as ulong e10, e2
Dim shared e as clong
Dim shared f as double
Dim as double tim = TIMER
CLS
a = allocate(len(__mpf_struct))
b = allocate(len(__mpf_struct))
u = allocate(len(__mpf_struct))
v = allocate(len(__mpf_struct))
k2 = allocate(len(__mpf_struct))
'log(x/y) with the Taylor series for atanh(x-y/x+y)
Sub ln (byval s as mpf_ptr, byval x as ulong, byval y as ulong)
Dim as mpf_ptr d = u, q = v
Dim k as ulong
'Möbius transformation
k = x: x -= y: y += k
If x <> 1 Then
Print "ln: illegal argument x - y <> 1"
End
End If
's = 1 / (x + y)
mpf_set_ui (s, y)
mpf_ui_div (s, 1, s)
'k2 = s * s
mpf_mul (k2, s, s)
mpf_set (d, s)
k = 1
Do
k += 2
'd *= k2
mpf_mul (d, d, k2)
'q = d / k
mpf_div_ui (q, d, k)
's += q
mpf_add (s, s, q)
f = mpf_get_d_2exp (@e, q)
Loop until abs(e) > e2
's *= 2
mpf_mul_2exp (s, s, 1)
End Sub
'Main
'n = 2^i * 3^j * 5^k
'log(n) = r * log(16/15) + s * log(25/24) + t * log(81/80)
'solve linear system for r, s, t
' 4 -3 -4| i
'-1 -1 4| j
'-1 2 -1| k
'examples
t = 1
select case t
case 1
n = 60
r = 41
s = 30
t = 18
'100 digits
case 2
n = 4800
r = 85
s = 62
t = 37
'8000 digits, 0.6 s
case 3
n = 9375
r = 91
s = 68
t = 40
'15625 digits, 2.5 s
case else
n = 18750
r = 98
s = 73
t = 43
'31250 digits, 12 s. @2.00GHz
end select
'decimal precision
e10 = n / .6
'binary precision
e2 = (1 + e10) / .30103
'initialize mpf's
mpf_set_default_prec (e2)
mpf_inits (a, b, u, v, k2, Cptr(mpf_ptr, 0))
'Compute log terms
ln b, 16, 15
'a = r * b
mpf_mul_ui (a, b, r)
ln b, 25, 24
'a += s * b
mpf_mul_ui (u, b, s)
mpf_add (a, a, u)
ln b, 81, 80
'a += t * b
mpf_mul_ui (u, b, t)
mpf_add (a, a, u)
''gmp_printf (!"log(%lu) %.*Ff\n", n, e10, a)
'B&M, algorithm B1
'a = -a, b = 1
mpf_neg (a, a)
mpf_set_ui (b, 1)
mpf_set (u, a)
mpf_set (v, b)
k = 0
n2 = n * n
'k2 = k * k
mpf_set_ui (k2, 0)
do
'k2 += 2k + 1
mpf_add_ui (k2, k2, (k shl 1) + 1)
k += 1
'b = b * n2 / k2
mpf_div (b, b, k2)
mpf_mul_ui (b, b, n2)
'a = (a * n2 / k + b) / k
mpf_div_ui (a, a, k)
mpf_mul_ui (a, a, n2)
mpf_add (a, a, b)
mpf_div_ui (a, a, k)
'u += a, v += b
mpf_add (u, u, a)
mpf_add (v, v, b)
f = mpf_get_d_2exp (@e, a)
Loop until abs(e) > e2
mpf_div (u, u, v)
gmp_printf (!"gamma %.*Ff (maxerr. 1e-%lu)\n", e10, u, e10)
gmp_printf (!"k = %lu\n\n", k)
gmp_printf (!"time: %.7f s\n", TIMER - tim)
end
- output:
gamma 0.5772156649015328606065120900824024310421593359399235988057672348848677267776646709369470632917467495 (maxerr. 1e-100) k = 255
The easy way
' ******************************************
'Subject: Euler's constant 0.5772...
'tested : FreeBasic 1.08.1 with mpfr 4.1.0
'-------------------------------------------
#include "gmp.bi"
#include "mpfr.bi"
dim as mpfr_ptr a = allocate(len(__mpfr_struct))
dim as ulong e2, e10
dim as double tim = TIMER
'decimal precision
e10 = 100
'binary precision
e2 = (1 + e10) / .30103
mpfr_init2 (a, e2)
mpfr_const_euler (a, MPFR_RNDN)
mpfr_printf (!"gamma %.*Rf\n\n", e10, a)
gmp_printf (!"time: %.7f s\n", TIMER - tim)
end
Burlesque
Subject to double rounding error, evaluates 33 partial terms in a series
33ro{JroJJJL[\/JL[\/nr\/{-1}\/.*FLJL[ro?^?*\/JL[{2}\/.*FL\/?^?*\/{1.+}m[J{lg}m[\/?/?*++\/1 3.0./\/?^.*}m[++-2 3 2lg.*./.*2lg2./.+
- Output:
0.5772156649015326
C
Single precision
/*********************************************
Subject: Comparing five methods for
computing Euler's constant 0.5772...
tested : tcc-0.9.27
--------------------------------------------*/
#include <math.h>
#include <stdio.h>
#define eps 1e-6
int main(void) {
double a, b, h, n2, r, u, v;
int k, k2, m, n;
printf("From the definition, err. 3e-10\n");
n = 400;
h = 1;
for (k = 2; k <= n; k++) {
h += 1.0 / k;
}
//faster convergence: Negoi, 1997
a = log(n +.5 + 1.0 / (24*n));
printf("Hn %.16f\n", h);
printf("gamma %.16f\nk = %d\n\n", h - a, n);
printf("Sweeney, 1963, err. idem\n");
n = 21;
double s[] = {0, n};
r = n;
k = 1;
do {
k += 1;
r *= (double) n / k;
s[k & 1] += r / k;
} while (r > eps);
printf("gamma %.16f\nk = %d\n\n", s[1] - s[0] - log(n), k);
printf("Bailey, 1988\n");
n = 5;
a = 1;
h = 1;
n2 = pow(2,n);
r = 1;
k = 1;
do {
k += 1;
r *= n2 / k;
h += 1.0 / k;
b = a; a += r * h;
} while (fabs(b - a) > eps);
a *= n2 / exp(n2);
printf("gamma %.16f\nk = %d\n\n", a - n * log(2), k);
printf("Brent-McMillan, 1980\n");
n = 13;
a = -log(n);
b = 1;
u = a;
v = b;
n2 = n * n;
k2 = 0;
k = 0;
do {
k2 += 2*k + 1;
k += 1;
a *= n2 / k;
b *= n2 / k2;
a = (a + b) / k;
u += a;
v += b;
} while (fabs(a) > eps);
printf("gamma %.16f\nk = %d\n\n", u / v, k);
printf("How Euler did it in 1735\n");
//Bernoulli numbers with even indices
double B2[] = {1.0,1.0/6,-1.0/30,1.0/42,-1.0/30,\
5.0/66,-691.0/2730,7.0/6,-3617.0/510,43867.0/798};
m = 7;
if (m > 9) return(0);
n = 10;
//n-th harmonic number
h = 1;
for (k = 2; k <= n; k++) {
h += 1.0 / k;
}
printf("Hn %.16f\n", h);
h -= log(n);
printf(" -ln %.16f\n", h);
//expansion C = -digamma(1)
a = -1.0 / (2*n);
n2 = n * n;
r = 1;
for (k = 1; k <= m; k++) {
r *= n2;
a += B2[k] / (2*k * r);
}
printf("err %.16f\ngamma %.16f\nk = %d", a, h + a, n + m);
printf("\n\nC = 0.57721566490153286...\n");
}
- output:
From the definition, err. 3e-10 Hn 6.5699296911765055 gamma 0.5772156645765731 k = 400 Sweeney, 1963, err. idem gamma 0.5772156645636311 k = 68 Bailey, 1988 gamma 0.5772156649015341 k = 89 Brent-McMillan, 1980 gamma 0.5772156649015329 k = 40 How Euler did it in 1735 Hn 2.9289682539682538 -ln 0.6263831609742079 err -0.0491674960726754 gamma 0.5772156649015325 k = 17 C = 0.57721566490153286...
Multi precision
From first principles
/**************************************************
Subject: Computation of Euler's constant 0.5772...
with the Brent-McMillan algorithm B1,
Math. Comp. 34 (1980), 305-312
tested : tcc-0.9.27 with gmp 6.2.0
-------------------------------------------------*/
#include <gmp.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
//multi-precision float pointers
mpf_ptr u, v, k2;
//precision parameters
unsigned long e10, e2;
long e;
double f;
//log(x/y) with the Taylor series for atanh(x-y/x+y)
void ln (mpf_ptr s, unsigned long x, unsigned long y) {
mpf_ptr d = u, q = v;
unsigned long k;
//Möbius transformation
k = x; x -= y; y += k;
if (x != 1) {
printf ("ln: illegal argument x - y != 1");
exit;
}
//s = 1 / (x + y)
mpf_set_ui (s, y);
mpf_ui_div (s, 1, s);
//k2 = s * s
mpf_mul (k2, s, s);
mpf_set (d, s);
k = 1;
do {
k += 2;
//d *= k2
mpf_mul (d, d, k2);
//q = d / k
mpf_div_ui (q, d, k);
//s += q
mpf_add (s, s, q);
f = mpf_get_d_2exp (&e, q);
} while (abs(e) < e2);
//s *= 2
mpf_mul_2exp (s, s, 1);
}
int main (void) {
mpf_ptr a = malloc(sizeof(__mpf_struct));
mpf_ptr b = malloc(sizeof(__mpf_struct));
u = malloc(sizeof(__mpf_struct));
v = malloc(sizeof(__mpf_struct));
k2 = malloc(sizeof(__mpf_struct));
//unsigned long integers
unsigned long k, n, n2, r, s, t;
clock_t tim = clock();
// n = 2^i * 3^j * 5^k
// log(n) = r * log(16/15) + s * log(25/24) + t * log(81/80)
// solve linear system for r, s, t
// 4 -3 -4| i
// -1 -1 4| j
// -1 2 -1| k
//examples
t = 1;
switch (t) {
case 1 :
n = 60;
r = 41;
s = 30;
t = 18;
//100 digits
break;
case 2 :
n = 4800;
r = 85;
s = 62;
t = 37;
//8000 digits, 0.6 s
break;
case 3 :
n = 9375;
r = 91;
s = 68;
t = 40;
//15625 digits, 2.5 s
break;
default :
n = 18750;
r = 98;
s = 73;
t = 43;
//31250 digits, 12 s. @2.00GHz
}
//decimal precision
e10 = n / .6;
//binary precision
e2 = (1 + e10) / .30103;
//initialize mpf's
mpf_set_default_prec (e2);
mpf_inits (a, b, u, v, k2, (mpf_ptr)0);
//Compute log terms
ln (b, 16, 15);
//a = r * b
mpf_mul_ui (a, b, r);
ln (b, 25, 24);
//a += s * b
mpf_mul_ui (u, b, s);
mpf_add (a, a, u);
ln (b, 81, 80);
//a += t * b
mpf_mul_ui (u, b, t);
mpf_add (a, a, u);
//gmp_printf ("log(%lu) %.*Ff\n", n, e10, a);
//B&M, algorithm B1
//a = -a, b = 1
mpf_neg (a, a);
mpf_set_ui (b, 1);
mpf_set (u, a);
mpf_set (v, b);
k = 0;
n2 = n * n;
//k2 = k * k
mpf_set_ui (k2, 0);
do {
//k2 += 2k + 1
mpf_add_ui (k2, k2, (k << 1) + 1);
k += 1;
//b = b * n2 / k2
mpf_div (b, b, k2);
mpf_mul_ui (b, b, n2);
//a = (a * n2 / k + b) / k
mpf_div_ui (a, a, k);
mpf_mul_ui (a, a, n2);
mpf_add (a, a, b);
mpf_div_ui (a, a, k);
//u += a, v += b
mpf_add (u, u, a);
mpf_add (v, v, b);
f = mpf_get_d_2exp (&e, a);
} while (abs(e) < e2);
mpf_div (u, u, v);
gmp_printf ("gamma %.*Ff (maxerr. 1e-%lu)\n", e10, u, e10);
gmp_printf ("k = %lu\n\n", k);
tim = clock() - tim;
printf("time: %.7f s\n",((double)tim)/CLOCKS_PER_SEC);
}
- output:
gamma 0.5772156649015328606065120900824024310421593359399235988057672348848677267776646709369470632917467495 (maxerr. 1e-100) k = 255
The easy way
/*******************************************
Subject: Euler's constant 0.5772...
tested : tcc-0.9.27 with mpfr 4.1.0
------------------------------------------*/
#include <gmp.h>
#include <mpfr.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main (void) {
mpfr_ptr a = malloc(sizeof(__mpfr_struct));
unsigned long e2, e10;
clock_t tim = clock();
//decimal precision
e10 = 100;
//binary precision
e2 = (1 + e10) / .30103;
mpfr_init2 (a, e2);
mpfr_const_euler (a, MPFR_RNDN);
mpfr_printf ("gamma %.*Rf\n\n", e10, a);
tim = clock() - tim;
gmp_printf ("time: %.7f s\n",((double)tim)/CLOCKS_PER_SEC);
}
C++
#include <array>
#include <cmath>
#include <iomanip>
#include <iostream>
double ByVaccaSeries(int numTerms)
{
// this method is simple but converges slowly
// calculate gamma by:
// 1 * (1/2 - 1/3) +
// 2 * (1/4 - 1/5 + 1/6 - 1/7) +
// 3 * (1/8 - 1/9 + 1/10 - 1/11 + 1/12 - 1/13 + 1/14 - 1/15) +
// 4 * ( . . . ) +
// . . .
double gamma = 0;
size_t next = 4;
for(double numerator = 1; numerator < numTerms; ++numerator)
{
double delta = 0;
for(size_t denominator = next/2; denominator < next; denominator+=2)
{
// calculate terms two at a time
delta += 1.0/denominator - 1.0/(denominator + 1);
}
gamma += numerator * delta;
next *= 2;
}
return gamma;
}
// based on the C entry
double ByEulersMethod()
{
//Bernoulli numbers with even indices
const std::array<double, 8> B2 {1.0, 1.0/6, -1.0/30, 1.0/42, -1.0/30,
5.0/66, -691.0/2730, 7.0/6};
const int n = 10;
//n-th harmonic number
const double h = [] // immediately invoked lambda
{
double sum = 1;
for (int k = 2; k <= n; k++) { sum += 1.0 / k; }
return sum - log(n);
}();
//expansion C = -digamma(1)
double a = -1.0 / (2*n);
double r = 1;
for (int k = 1; k < ssize(B2); k++)
{
r *= n * n;
a += B2[k] / (2*k * r);
}
return h + a;
}
int main()
{
std::cout << std::setprecision(16) << "Vacca series: " << ByVaccaSeries(32);
std::cout << std::setprecision(16) << "\nEulers method: " << ByEulersMethod();
}
- Output:
Vacca series: 0.5772156610598274 Eulers method: 0.5772156649015325
Clojure
(let [n 1e10]
(loop [i 1
out (- (Math/log n))]
(if (<= i n)
(recur (inc i) (+ out (/ 1.0 i)))
out)))
- Output:
Gives: 0.5772156649484047 Compared to the true value: 0.5772156649015328...
Delphi
This programs demonstrates the basic method of calculating the Euler number. It illustrates how the number of iterations increases the accuracy.
function ComputeEuler(N: int64): double;
{Compute Eurler number with N-number of iterations}
var I: integer;
var A: double;
begin
Result:=0;
for I:=1 to N-1 do
Result:=Result + 1 / I;
A:=Ln(N + 0.5 + 1/(24.0*N));
Result:=Result-A;
end;
procedure ShowEulersNumber(Memo: TMemo);
{Show Euler numbers at various levels of precision}
var Euler,G,A,Error: double;
var N: integer;
const Correct =0.57721566490153286060651209008240243104215933593992;
procedure ShowEulerError(N: int64);
{Show Euler number and Error}
begin
Euler:=ComputeEuler(N);
Error:=Correct-Euler;
Memo.Lines.Add('N = '+FloatToStrF(N,ffNumber,18,0));
Memo.Lines.Add('Euler='+FloatToStrF(Euler,ffFixed,18,18));
Memo.Lines.Add('Error='+FloatToStrF(Error,ffFixed,18,18));
Memo.Lines.Add('');
end;
begin
{Compute Euler number with iterations ranging 10 to 10^9}
for N:=1 to 9 do
begin
ShowEulerError(Trunc(Power(10,N)));
end;
end;
- Output:
N = 10 Euler=0.477196250122325250 Error=0.100019414779207616 N = 100 Euler=0.567215644212103243 Error=0.010000020689429618 N = 1,000 Euler=0.576215664880711742 Error=0.001000000020821119 N = 10,000 Euler=0.577115664901475256 Error=0.000100000000057605 N = 100,000 Euler=0.577205664901386584 Error=0.000010000000146277 N = 1,000,000 Euler=0.577214664900591146 Error=0.000001000000941715 N = 10,000,000 Euler=0.577215564898391875 Error=0.000000100003140985 N = 100,000,000 Euler=0.577215654895336883 Error=0.000000010006195978 N = 1,000,000,000 Euler=0.577215664060567235 Error=0.000000000840965626 Elapsed Time: 4.716 Sec.
EasyLang
fastfunc gethn n .
i = 1
while i <= n
hn += 1 / i
i += 1
.
return hn
.
e = 2.718281828459045235
n = 10e8
numfmt 9 0
print gethn n - log10 n / log10 e
FutureBasic
void local fn Euler
long n = 10000000, k
double a, h = 1.0
for k = 2 to n
h += 1 / k
next
a = log( n + 0.5 + 1 / ( 24 * n ) )
printf @"From the definition, err. 3e-10"
printf @"Hn %.15f", h
printf @"gamma %.15f", h - a
printf @"k = %ld\n", n
printf @"C %.15f", 0.5772156649015328
end fn
CFTimeInterval t
t = fn CACurrentMediaTime
fn Euler
printf @"\vCompute time: %.3f ms",(fn CACurrentMediaTime-t)*1000
HandleEvents
- Output:
From the definition, err. 3e-10 Hn 16.695311365857272 gamma 0.577215664898954 k = 10000000 C 0.577215664901533 Compute time: 67.300 ms
J
We can approximate euler's constant using the difference between the reciprocal and the gamma function of a small number:
(% - !@<:) 2^_27
0.577216
For higher accuracy we can use a variation on the C implementation which was attributed to Richard P. Brent and Edwin M. McMillan:
Euler=: {{
A=.B=. ^.1r13 1x1
r=. j=. 0
whilst. (r=.%/B)~:!.0(r) do.
B=. B+A=. (j,1)%~+/\.A*169%(1,j)*(j=.j+1)
end.
r
}}0
With J configured for 16 digits of display precision (9!:11(16)
) we can see that this gave us:
Euler
0.5772156649015329
Java
/**
* Using a simple formula derived from Hurwitz zeta function,
* as described on https://en.wikipedia.org/wiki/Euler%27s_constant,
* gives a result accurate to 12 decimal places.
*/
public class EulerConstant {
public static void main(String[] args) {
System.out.println(gamma(1_000_000));
}
private static double gamma(int N) {
double gamma = 0.0;
for ( int n = 1; n <= N; n++ ) {
gamma += 1.0 / n;
}
gamma -= Math.log(N) + 1.0 / ( 2 * N );
return gamma;
}
}
- Output:
0.5772156649007147
jq
Translated from C (Bailey, 1988)
Works with gojq, the Go implementation of jq
# Bailey, 1988
def bailey($n; $eps):
pow(2; $n) as $n2
| {a :1, b: 0, h: 1, r: 1, k: 1}
| until( (.b - .a)|fabs <= $eps;
.k += 1
| .r *= ($n2 / .k)
| .h += (1.0 / .k)
| .b = .a
| .a += (.r * .h) )
| (.a * $n2 / ($n2|exp) ) - ($n * (2|log)) ;
- Output:
bailey(5; 1E-6) 0.5772156649015341
Julia
display(MathConstants.γ) # γ = 0.5772156649015...
Lambdatalk
Following the definition with an improvment from Negoi.
{def negoi
{lambda {:n}
{let { {:n :n}
{:h {+ {S.map {lambda {:k} {/ 1 :k}} {S.serie 1 :n}}} }
{:a {log {+ :n 0.5 {/ 1 {* 24 :n}}}}} // Negoi, 1997
} {div}-> Hn :h
{div}gamma {- :h :a}
{div}k :n
}}}
-> negoi
{negoi 400}
-> Hn 6.5699296911765055
gamma 0.5772156645765731 with k = 400
(0.57721566457657 target)
Following Sweeney
{def sweeney
{def sweeney.set!
{lambda {:s :r :k :i}
{A.set! :i {+ {A.get :i :s} {/ :r :k}} :s}
}}
{def sweeney.loop
{lambda {:n :s :r :k}
{if {<= :r 1.e-10}
then gamma = {- {A.get 1 :s} {A.get 0 :s} {log :n}} with k=:k
else {sweeney.loop :n
{sweeney.set! :s {* :r {/ :n :k}} :k {% :k 2}}
{* :r {/ :n :k}}
{+ :k 1} }
}}}
{lambda {:n}
{sweeney.loop :n {A.new 0 :n} :n 2} }}
-> sweeney
{sweeney 21}
-> gamma = 0.577215664563631 with k=76
(0.57721566456363 target)
Lua
A value using 100,000,000 iterations of the harmonic series computes in less than a second and is correct to eight decimal places.
function computeGamma (iterations, decimalPlaces)
local Hn = 1
for i = 2, iterations do
Hn = Hn + (1/i)
end
local gamma = tostring(Hn - math.log(iterations))
return tonumber(gamma:sub(1, decimalPlaces + 2))
end
print(computeGamma(10^8, 8))
- Output:
0.57721566
Mathematica /Wolfram Language
N[EulerGamma, 1000]
- Output:
0.57721566490153286060651209008240243104215933593992359880576723488486772677766467093694706329174674 9514631447249807082480960504014486542836224173997644923536253500333742937337737673942792595258247094 9160087352039481656708532331517766115286211995015079847937450857057400299213547861466940296043254215 1905877553526733139925401296742051375413954911168510280798423487758720503843109399736137255306088933 1267600172479537836759271351577226102734929139407984301034177717780881549570661075010161916633401522 7893586796549725203621287922655595366962817638879272680132431010476505963703947394957638906572967929 6010090151251959509222435014093498712282479497471956469763185066761290638110518241974448678363808617 4945516989279230187739107294578155431600500218284409605377243420328547836701517739439870030237033951 8328690001558193988042707411542227819716523011073565833967348717650491941812300040654693142999297779 569303100503086303418569803231083691640025892970890985486825777364288253954925873629596133298574739302
Maxima
%gamma,numer;
- Output:
0.5772156649015329
Nim
import std/math
const n = 1e6
var result = 1.0
for i in 2..int(n):
result += 1/i
echo result - ln(n)
- Output:
0.5772161649007153
PARI/GP
built-in:
\l "euler_const.log"
\p 100
print("gamma ", Euler);
\q
PascalABC.NET
const
n = 1_000_000;
begin
var result := 1.0;
for var i := 2 to n do
result += 1 / i;
writeln(result - ln(n));
end.
- Output:
0.577216164900715
Perl
#!/usr/bin/perl
use strict; # https://en.wikipedia.org/wiki/Euler%27s_constant
use warnings;
use List::Util qw( sum );
print sum( map 1 / $_, 1 .. 1e6) - log 1e6, "\n";
- Output:
0.577216164900715
Phix
part 1 (max 12dp)
Translation of Perl, with the same accuracy limitation
-- demo\rosetta\Eulers_constant.exw with javascript_semantics constant C = sum(sq_div(1,tagset(1e6)))-log(1e6) printf(1,"gamma %.12f (max 12d.p. of accuracy)\n",C)
- Output:
gamma 0.577216164901 (max 12d.p. of accuracy)
part 2 (first principles)
Translation of C, from first principles.
without js -- no mpfr_get_d_2exp() in mpfr.js as yet requires("1.0.2") -- mpfr_get_d_2exp(), mpfr_addmul_si() include mpfr.e mpfr u, v, k2; integer e, e10, e2 atom f //log(x/y) with the Taylor series for atanh(x-y/x+y) procedure ln(mpfr s, integer x, y) mpfr d = u, q = v; assert((x-y)==1) mpfr_set_si(s, x+y) mpfr_si_div(s, 1, s) // s = 1 / (x + y) mpfr_mul(k2, s, s) // k2 = s * s mpfr_set(d, s) integer k = 1 while true do k += 2; mpfr_mul(d, d, k2) // d *= k2 mpfr_div_si(q, d, k) // q = d / k mpfr_add(s, s, q) // s += q {f,e} = mpfr_get_d_2exp(q) if abs(e)>=e2 then exit end if end while mpfr_mul_si(s, s, 2) //s *= 2 end procedure mpfr a, b integer k, n = 60, -- (required precision in decimal dp *6/10) n2, r = 41, s = 30, t = 18; // n = 2^i * 3^j * 5^k // log(n) = r * log(16/15) + s * log(25/24) + t * log(81/80) // solve linear system for r, s, t // 4 -3 -4| i // -1 -1 4| j // -1 2 -1| k //decimal precision e10 = floor(n/0.6) //binary precision e2 = floor((1 + e10) / 0.30103) mpfr_set_default_precision(e2) {a, b, u, v, k2} = mpfr_inits(5) //Compute log terms ln(b, 16, 15) mpfr_mul_si(a, b, r) // a = r * b ln(b, 25, 24) mpfr_addmul_si(a, b, s) // a += s * b ln(b, 81, 80) mpfr_addmul_si(a, b, t) // a += t * b mpfr_neg(a, a) // a = -a mpfr_set_si(b, 1) // b = 1 mpfr_set (u, a) mpfr_set (v, b) k = 0; n2 = n * n; mpfr_set_si(k2, 0) // k2 = k * k (as below) while true do mpfr_add_si(k2, k2, k*2+1) // k2 += 2k + 1 k += 1; mpfr_div(b, b, k2) mpfr_mul_si(b, b, n2) // b = b * n2 / k2 mpfr_div_si(a, a, k) mpfr_mul_si(a, a, n2) mpfr_add (a, a, b) mpfr_div_si(a, a, k) // a = (a * n2 / k + b) / k mpfr_add(u, u, a) // u += a mpfr_add(v, v, b) // v += b {f,e} = mpfr_get_d_2exp (a) if abs(e)>=e2 then exit end if end while mpfr_div(u, u, v) string su = mpfr_get_fixed(u,e10) printf(1,"gamma %s (maxerr. 1e-%d)\n", {su, e10})
- Output:
gamma 0.5772156649015328606065120900824024310421593359399235988057672348848677267776646709369470632917467494 (maxerr. 1e-100)
part 3 (the easy way)
without js -- no mpfr_const_euler() in mpfr.js as yet requires("1.0.1") -- mpfr_const_euler() include mpfr.e mpfr gamma = mpfr_init(0,-100) mpfr_const_euler(gamma) printf(1,"gamma %s (mpfr_const_euler)\n",{mpfr_get_fixed(gamma,100)})
(matches part 2 except for the 100th decimal place)
- Output:
gamma 0.5772156649015328606065120900824024310421593359399235988057672348848677267776646709369470632917467495 (mpfr_const_euler)
Picat
List comprehension
main =>
Gamma = 0.57721566490153286060651209008240,
println(Gamma),
foreach(N in 1..8)
G = e(10**N),
println([n=N,g=G,diff=G-Gamma])
end.
e(N) = [1.0/I : I in 1..N].sum-log(N).
- Output:
0.577215664901533 [n = 1,g = 0.626383160974208,diff = 0.049167496072675] [n = 2,g = 0.582207331651529,diff = 0.004991666749996] [n = 3,g = 0.577715581568206,diff = 0.000499916666674] [n = 4,g = 0.577265664068165,diff = 0.000049999166632] [n = 5,g = 0.577220664893106,diff = 0.000004999991574] [n = 6,g = 0.577216164900715,diff = 0.000000499999182] [n = 7,g = 0.577215714898951,diff = 0.000000049997419] [n = 8,g = 0.577215669900188,diff = 0.000000004998655]
Loop
e2(N) = E-log(N) =>
E = 1,
foreach(I in 2..N)
E := E + 1/I
end.
main =>
Gamma = 0.577215664901532860606512090082402,
println(gamma=Gamma),
member(N, 1..23),
G = gamma(N),
println([n=N,g=G,diff=G-Gamma]),
fail,
nl.
gamma(N) = Gamma =>
Gamma = 1/2 - 1/3,
foreach(I in 2..N)
Power = 2**I,
Sign = -1,
Term = 0,
foreach(Denominator in Power..(2*Power-1))
Sign := Sign * -1,
Term := Term + Sign / Denominator
end,
Gamma := Gamma + I*Term
end.
- Output:
[n = 1,g = 0.166666666666667,diff = -0.410548998234866] [n = 2,g = 0.314285714285714,diff = -0.262929950615819] [n = 3,g = 0.416741591741592,diff = -0.160474073159941] [n = 4,g = 0.482164184398886,diff = -0.095051480502647] [n = 5,g = 0.522141654090275,diff = -0.055074010811257] [n = 6,g = 0.545853770405349,diff = -0.031361894496184] [n = 7,g = 0.559605750992416,diff = -0.017609913909116] [n = 8,g = 0.567441138957738,diff = -0.009774525943794] [n = 9,g = 0.571842107494027,diff = -0.005373557407506] [n = 10,g = 0.574285301882304,diff = -0.002930363019229] [n = 11,g = 0.57562856705805,diff = -0.001587097843483] [n = 12,g = 0.576361123043496,diff = -0.000854541858037] [n = 13,g = 0.576757887880701,diff = -0.000457777020832] [n = 14,g = 0.576971520706463,diff = -0.00024414419507] [n = 15,g = 0.577085964243776,diff = -0.000129700657756] [n = 16,g = 0.577147000098518,diff = -0.000068664803014] [n = 17,g = 0.577179425210813,diff = -0.00003623969072] [n = 18,g = 0.577196591397621,diff = -0.000019073503912] [n = 19,g = 0.577205651316587,diff = -0.000010013584946] [n = 20,g = 0.57721041969158,diff = -0.000005245209953] [n = 21,g = 0.577212923087556,diff = -0.000002741813977] [n = 22,g = 0.577214234389975,diff = -0.000001430511558] [n = 23,g = 0.577214919843452,diff = -0.000000745058081]
Processing
/*********************************************
Subject: Comparing five methods for
computing Euler's constant 0.5772...
// https://rosettacode.org/wiki/Euler%27s_constant_0.5772...
--------------------------------------------*/
double a, b, h, n2, r, u, v;
float floatA, floatB, floatN2;
int k, k2, m, n;
double eps = 1e-6;
void setup() {
size(100, 100);
noLoop();
}
void draw() {
println("From the definition, err. 3e-10\n");
n = 400;
h = 1;
for (int k = 2; k <= n; k++) {
h += 1.0 / k;
}
//faster convergence: Negoi, 1997
a = log(n +.5 + 1.0 / (24*n));
println("Hn ", h);
println("gamma ", h - a);
println("k = ", n);
println("");
println("Sweeney, 1963, err. idem");
n = 21;
double s[] = {0, n};
r = n;
k = 1;
while (r > eps) {
k ++;
r *= (double) n / k;
s[k & 1] = s[k & 1] + r / k;
}
// println("gamma %.16f\nk = %d\n\n", s[1] - s[0] - log(n), k);
println("Hn ", h);
println("gamma ", s[1] - s[0] - log(n));
println("k = ", k);
println("");
println("Bailey, 1988");
n = 5;
floatA = 1;
h = 1;
floatN2 = pow(2, n);
r = 1;
k = 1;
while (abs(floatB - floatA) > eps) {
k += 1;
r *= floatN2 / k;
h += 1.0 / k;
floatB = floatA;
floatA += r * h;
}
floatA *= floatN2 / exp(floatN2);
println("gamma ", floatA - n * log(2));
println("k = ", k);
println("");
println("Brent-McMillan, 1980");
n = 13;
floatA = -log(n);
floatB = 1;
u = a;
v = b;
n2 = n * n;
k2 = 0;
k = 0;
while (abs(floatA) > eps) {
k2 += 2*k + 1;
k += 1;
floatA *= n2 / k;
floatB *= n2 / k2;
floatA = (floatA + floatB) / k;
u += floatA;
v += floatB;
}
println("gamma ", u / v);
println("k ", k);
println("How Euler did it in 1735\n");
//Bernoulli numbers with even indices
double[] B2 = new double[11];
B2[1] = 1.0;
B2[2] = 1.0/6;
B2[3] = -1.0/30;
B2[4] = 1.0/42;
B2[5] = -1.0/30;
B2[6] = 5.0/66;
B2[7] = -691.0/2730;
B2[8] = 7.0/6;
B2[9] = -3617.0/510;
B2[10]= 43867.0/798;
m = 7;
n = 10;
//n-th harmonic number
h = 1;
for (k = 2; k <= n; k++) {
h += 1.0 / k;
}
println("Hn ", h);
h -= log(n);
println(" -ln ", h);
//expansion C = -digamma(1)
a = -1.0 / (2*n);
n2 = n * n;
r = 1;
for (k = 1; k <= m; k++) {
r *= n2;
a += B2[k] / (2*k * r);
}
println("");
println("err ", a);
println("gamma ", h + a );
println("k = ", n + m);
println("");
println("C = 0.57721566490153286...\n");
}
- Output:
From the definition, err. 3e-10 Hn 6.569929751800373 gamma 0.577215823577717 k = 400 Sweeney, 1963, err. idem Hn 6.569929751800373 gamma 0.5772155784070492 k = 68 Bailey, 1988 gamma 0.5772176 k = 67 Brent-McMillan, 1980 gamma 0.5772157269353247 k 40 How Euler did it in 1735 Hn 2.9289682805538177 -ln 0.6263831555843353 err -0.044995839604388355 gamma 0.581387315979947 k = 17 C = 0.57721566490153286...
Python
# /**************************************************
# Subject: Computation of Euler's constant 0.5772...
# with Euler's Zeta Series.
# tested : Python 3.11
# -------------------------------------------------*/
from scipy import special as s
def eulers_constant(n):
k = 2
euler = 0
while k <= n:
euler += (s.zeta(k) - 1)/k
k += 1
return 1 - euler
print(eulers_constant(47))
- Output:
0.577215664901533
Racket
#lang racket/base
(require math/number-theory
math/base)
gamma.0
;; if you want to work it out the hard way...
(define (H n)
(for/sum ((i n)) (/ (add1 i))))
(define (g #:n (n 10) #:k (k 7))
(+ (- (H n)
(log n)
(/ (* n 2)))
(for/sum ((2k (in-range 2 (* 2 (add1 k)) 2)))
(/ (bernoulli-number 2k) (* (expt n 2k) 2k)))))
(g)
- Output:
0.5772156649015329 0.5772156649015324
Raku
# 20211124 Raku programming solution
sub gamma (\N where N > 1) { # Vacca series https://w.wiki/4ybp
# convert terms to FatRat for arbitrary precision
return (1/2 - 1/3) + [+] (2..N).race.map: -> \n {
my ($power, $sign, $term) = 2**n, -1;
for ($power..^2*$power) { $term += ($sign = -$sign) / $_ }
n*$term
}
}
say gamma 23 ;
- Output:
0.5772149198434515
REXX
Libraries: How to use
Library: Numbers
Library: Functions
Library: Constants
Brent-McMillan
Using arbitrary precision. You may specify this as parameter, default is 100 decimal places.
arg n; if n = '' then n = 100; numeric digits n
parse version version; say version; glob. = ''; fact. = 0
say 'Euler-Mascheroni constant to' n 'decimal places'
say 'Method Brent-McMillan'
say
call time('r'); a = Brent(); e = format(time('e'),,3)
say 'Brent ' a '('e 'seconds)'
call time('r'); a = TrueValue(); e = format(time('e'),,3)
say 'True value' a '('e 'seconds)'
exit
Brent:
procedure expose fact. glob. work.
numeric digits Digits()+2
/* Brent McMillan */
n = Ceil((Digits()*Ln(10)+Ln(Pi()))*0.25); m = Ceil(2.07*Digits())
n2 = n*n; ak = -Ln(n); bk = 1; s = ak; v = 1
do k = 1 to m
bk = bk*n2/(k*k); ak = (ak*n2/k+bk)/k
s = s+ak; v = v+bk
end
y = s/v
numeric digits Digits()-2
return y+0
TrueValue:
procedure
return 0.5772156649015328606065120900824024310421593359399235988057672348848677267776646709369470632917467495+0
include Constants
include Functions
include Numbers
Running with the default, the program gives:
- Output:
REXX-Regina_3.9.6(MT) 5.00 29 Apr 2024 Euler-Mascheroni constant to 100 decimal places Method Brent-McMillan Brent 0.5772156649015328606065120900824024310421593359399235988057672348848677267776646709369470632917467495 (0.023 seconds) True value 0.5772156649015328606065120900824024310421593359399235988057672348848677267776646709369470632917467495 (0.000 seconds)
RPL
From the definition, with Negoi's convergence improvement
≪ → n
≪ 1
2 n FOR k k INV + NEXT
n .5 + 24 n * INV + LN -
≫ ≫ ‘GAMMA1’ STO
Sweeney method
≪ 0 OVER R→C 1E-6 → n s eps
≪ n 1
DO
1 + SWAP
OVER / n * SWAP
DUP2 /
IF OVER 2 MOD THEN (0,1) * END 's' STO+
UNTIL OVER eps < END
DROP2
s C→R SWAP - n LN -
≫ ≫ ‘GAMMA2’ STO
400 GAMMA1 21 GAMMA2
- Output:
2: .57721566456 1: .57717756228
Ruby
n = 1e6
p (1..n).sum{ 1.0/_1 } - Math.log(n)
- Output:
0.5772161649014507 #12 digits accurate
Rust
// 20220322 Rust programming solution
fn gamma(N: u32) -> f64 { // Vacca series https://w.wiki/4ybp
return 1f64 / 2f64 - 1f64 / 3f64
+ ((2..=N).map(|n| {
let power: u32 = 2u32.pow(n);
let mut sign: f64 = -1f64;
let mut term: f64 = 0f64;
for denominator in power..=(2 * power - 1) {
sign *= -1f64;
term += sign / f64::from(denominator);
}
return f64::from(n) * term;
}))
.sum::<f64>();
}
fn main() {
println!("{}", gamma(23));
}
- Output:
0.5772149198434514
Scala
/**
* Using a simple formula derived from Hurwitz zeta function,
* as described on https://en.wikipedia.org/wiki/Euler%27s_constant,
* gives a result accurate to 11 decimal places: 0.57721566490...
*/
object EulerConstant extends App {
println(gamma(1_000_000))
private def gamma(N: Int): Double = {
val sumOverN = (1 to N).map(1.0 / _).sum
sumOverN - Math.log(N) - 1.0 / (2 * N)
}
}
- Output:
0.5772156649007153
Scheme
; Procedure to compute factorial.
(define fact
(lambda (n)
(if (<= n 0)
1
(* n (fact (1- n))))))
; Compute Euler's gamma constant as the difference of log(n) from a sum.
; See section 2.3 of <http://numbers.computation.free.fr/Constants/Gamma/gamma.html>.
(define gamma
(lambda (n)
(let ((sum 0))
(do ((k 1 (1+ k)))
((> k (* 3.5911 n)) (- sum (log n)))
(set! sum (+ sum (/ (* (expt -1 (1- k)) (expt n k)) (* k (fact k)))))))))
; Show Euler's gamma constant computed at log(100).
(printf "Euler's gamma constant: ~a~%" (gamma 100))
- Output:
Euler's gamma constant: 0.5772156649015328
Sidef
Built-in:
# 100 decimals of precision
local Num!PREC = 4*100
say Num.EulerGamma
- Output:
0.5772156649015328606065120900824024310421593359399235988057672348848677267776646709369470632917467495
Several formulas:
const n = (ARGV ? Num(ARGV[0]) : 50) # number of iterations
define ℯ = Num.e
define π = Num.pi
define γ = Num.EulerGamma
func display(r, t) {
say "#{r}\terror: #{ '%.0g' % abs(r - t) }"
}
# Original definition of the Euler-Mascheroni constant, due to Euler (1731)
display(sum(1..n, {|n| 1/n }) - log(n), γ)
# Formula due to Euler (best convergence)
display(harmfrac(n) - log(n) - 1/(2*n) - sum(1..n, {|k|
-bernoulli(2*k) / (2*k) / n**(2*k)
}), γ)
# Formula derived from the above formula of Euler,
# using approximations of Bernoulli numbers.
display(harmfrac(n) - log(n) - 1/(2*n) - sum(1..n, {|k|
(-1)**k * 4 * sqrt(π*k) * (π * ℯ)**(-2*k) * k**(2*k) / (2*k) / n**(2*k)
}), γ)
# Euler-Mascheroni constant, involving zeta(n)
display(1 - sum(2..(n+1), {|n|
(zeta(n) - 1) / n
}), γ)
# Limit_{n->Infinity} zeta((n+1)/n) - n} = gamma
display(zeta((n+1)/n) - n, γ)
# Series due to Euler (1731).
display(sum(2..(n+1), {|n|
(-1)**n * zeta(n) / n
}), γ)
# Formula due to Euler in terms of log(2) and the odd zeta values
display(3/4 - log(2)/2 + sum(1..n, {|n|
(1 - 1/(2*n + 1)) * (zeta(2*n + 1) - 1)
}), γ)
# Formula due to Euler in terms of log(2) and the odd zeta values (VII)
display(log(2) - sum(1..n, {|n|
zeta(2*n + 1) / (2*n + 1) / 2**(2*n)
}), γ)
# Formula due to Vacca (1910)
display(sum(1..n, {|n|
(-1)**n * floor(log2(n)) / n
}), γ)
- Output:
0.58718233290127899894172100505421724484389898107 error: 0.01 0.57721566490153286060651209008240243104215933594 error: 2e-58 0.577201775274185974649592917416402750312879661543 error: 1e-05 0.577215664901532868991217643213156967011395887777 error: 8e-18 0.57867004101560321761330253540741574969540128177 error: 0.001 0.567507841748305076772446986005418728718501189232 error: 0.01 0.577215664901532860606512090082272222693164663104 error: 1e-31 0.57721566490153286060651209008240496797924366087 error: 3e-33 0.611009392556929160631547597803236563977259982583 error: 0.03
V (Vlang)
import math
const eps = 1e-6
fn main() {
//.5772
println("From the definition, err. 3e-10")
mut n := 400
mut h := 1.0
for k in 2..n+1 {
h += 1.0/f64(k)
}
//faster convergence: Negoi, 1997
mut a := math.log(f64(n) + 0.5 + 1.0/f64(24*n))
println("Hn ${h:0.16f}")
println("gamma ${h-a:0.16f}\nk = $n\n")
println("Sweeney, 1963, err. idem")
n = 21
mut s := [0.0, f64(n)]
mut r := f64(n)
mut k := 1
for {
k++
r *= f64(n) / f64(k)
s[k & 1] += r/f64(k)
if r <= eps {
break
}
}
println("gamma ${s[1] - s[0] - math.log(n):0.16f}\nk = $k\n")
println("Bailey, 1988")
n = 5
a = 1.0
h = 1.0
mut n2 := math.pow(f64(2),f64(n))
r = 1
k = 1
for {
k++
r *= n2 / f64(k)
h += 1/f64(k)
b := a
a += r * h
if math.abs(b-a) <= eps {
break
}
}
a *= n2 / math.exp(n2)
println("gamma ${a - n * math.log(2):.16f}\nk = $k\n")
println("Brent-McMillan, 1980")
n = 13
a = -math.log(n)
mut b := 1.0
mut u := a
mut v := b
n2 = n * n
mut k2 := 0
k = 0
for {
k2 += 2*k + 1
k++
a *= n2 / f64(k)
b *= n2 / f64(k2)
a = (a + b)/f64(k)
u += a
v += b
if math.abs(a) <= eps {
break
}
}
println("gamma ${u/v:0.16f}\nk = $k\n")
println("How Euler did it in 1735")
// Bernoulli numbers with even indices
b2 := [1.0, 1.0/6, -1.0/30, 1.0/42, -1.0/30, 5.0/66, -691.0/2730, 7.0/6, -3617.0/510, 43867.0/798]
m := 7
n = 10
// n'th harmonic number
h = 1.0
for kz in 2..n+1 {
h += 1.0/f64(kz)
}
println("Hn ${h:0.16f}")
h -= math.log(n)
println(" -ln ${h:0.16f}")
// expansion C = -digamma(1)
a = -1.0 / (2.0*f64(n))
n2 = f64(n * n)
r = 1
for kq in 1..m+1 {
r *= n2
a += b2[kq] / (2.0*f64(kq)*r)
}
println("err ${a:0.16f}\ngamma ${h+a:0.16f}\nk = ${n+m}")
println("\nC = 0.57721566490153286...")
}
- Output:
Same as C entry
Wren
Single precision (Cli)
Note that, whilst internally double arithmetic is carried out to the same precision as C (Wren is written in C), printing doubles is effectively limited to a maximum of 14 decimal places.
import "./fmt" for Fmt
var eps = 1e-6
System.print("From the definition, err. 3e-10")
var n = 400
var h = 1
for (k in 2..n) h = h + 1/k
//faster convergence: Negoi, 1997
var a = (n + 0.5 + 1/(24*n)).log
Fmt.print("Hn $0.14f", h)
Fmt.print("gamma $0.14f\nk = $d\n", h - a, n)
System.print("Sweeney, 1963, err. idem")
n = 21
var s = [0, n]
var r = n
var k = 1
while (true) {
k = k + 1
r = r * n / k
s[k & 1] = s[k & 1] + r/k
if (r <= eps) break
}
Fmt.print("gamma $0.14f\nk = $d\n", s[1] - s[0] - n.log, k)
System.print("Bailey, 1988")
n = 5
a = 1
h = 1
var n2 = 2.pow(n)
r = 1
k = 1
while (true) {
k = k + 1
r = r * n2 / k
h = h + 1/k
var b = a
a = a + r * h
if ((b-a).abs <= eps) break
}
a = a * n2 / n2.exp
Fmt.print("gamma $0.14f\nk = $d\n", a - n * 2.log, k)
System.print("Brent-McMillan, 1980")
n = 13
a = -n.log
var b = 1
var u = a
var v = b
n2 = n * n
var k2 = 0
k = 0
while (true) {
k2 = k2 + 2*k + 1
k = k + 1
a = a * n2 / k
b = b * n2 / k2
a = (a + b)/k
u = u + a
v = v + b
if (a.abs <= eps) break
}
Fmt.print("gamma $0.14f\nk = $d\n", u / v, k)
System.print("How Euler did it in 1735")
// Bernoulli numbers with even indices
var b2 = [1, 1/6, -1/30, 1/42, -1/30, 5/66, -691/2730, 7/6, -3617/510, 43867/798]
var m = 7
n = 10
// n'th harmonic number
h = 1
for (k in 2..n) h = h + 1/k
Fmt.print("Hn $0.14f", h)
h = h - n.log
Fmt.print(" -ln $0.14f", h)
// expansion C = -digamma(1)
a = -1 / (2*n)
n2 = n * n
r = 1
for (k in 1..m) {
r = r * n2
a = a + b2[k] / (2*k*r)
}
Fmt.print("err $0.14f\ngamma $0.14f\nk = $d", a, h + a, n + m)
System.print("\nC = 0.57721566490153286...")
- Output:
From the definition, err. 3e-10 Hn 6.56992969117651 gamma 0.57721566457657 k = 400 Sweeney, 1963, err. idem gamma 0.57721566456363 k = 68 Bailey, 1988 gamma 0.57721566490154 k = 89 Brent-McMillan, 1980 gamma 0.57721566490153 k = 40 How Euler did it in 1735 Hn 2.92896825396825 -ln 0.62638316097421 err -0.04916749607268 gamma 0.57721566490153 k = 17 C = 0.57721566490153286...
Multi precision (Embedded)
The display is limited to 100 digits for all four examples as I couldn't see much point in showing them all.
import "./gmp" for Mpf
var euler = Fn.new { |n, r, s, t|
// decimal precision
var e10 = (n/0.6).floor
// binary precision
var e2 = ((1 + n/0.6)/0.30103).round
Mpf.defaultPrec = e2
var b = Mpf.new().log(Mpf.from(16).div(15))
var a = b.mul(r)
b = Mpf.new().log(Mpf.from(25).div(24))
a.add(b.mul(s))
b = Mpf.new().log(Mpf.from(81).div(80))
var u = b * t
a.add(u).neg
b.set(1)
u.set(a)
var v = Mpf.from(b)
var k = 0
var n2 = n * n
var k2 = Mpf.zero
while (true) {
k2.add((k << 1) + 1)
k = k + 1
b.mul(n2).div(k2)
a.mul(n2).div(k).add(b).div(k)
u.add(a)
v.add(b)
var e = Mpf.frexp(a)[1]
if (e.abs >= e2) break
}
u.div(v)
System.print("gamma %(u.toString(10, 100)) (maxerr. 1e-%(e10))")
System.print("k = %(k)")
}
var start = System.clock
euler.call(60, 41, 30, 18)
euler.call(4800, 85, 62, 37)
euler.call(9375, 91, 68, 40)
euler.call(18750, 98, 73, 43)
System.print("\nTook %(System.clock - start) seconds.")
- Output:
gamma 0.5772156649015328606065120900824024310421593359399235988057672348848677267776646709369470632917467495 (maxerr. 1e-100) k = 255 gamma 0.5772156649015328606065120900824024310421593359399235988057672348848677267776646709369470632917467495 (maxerr. 1e-8000) k = 20462 gamma 0.5772156649015328606065120900824024310421593359399235988057672348848677267776646709369470632917467495 (maxerr. 1e-15625) k = 39967 gamma 0.5772156649015328606065120900824024310421593359399235988057672348848677267776646709369470632917467495 (maxerr. 1e-31250) k = 79936 Took 2.330538 seconds.
The easy way (Embedded)
import "./gmp" for Mpf
var prec = (101/0.30103).round
var gamma = Mpf.euler(prec)
System.print(gamma.toString(10, 100))
- Output:
0.5772156649015328606065120900824024310421593359399235988057672348848677267776646709369470632917467495
XPL0
\*********************************************
\Subject: Comparing five methods for
\ computing Euler's constant 0.5772...
\---------------------------------------------
include xpllib; \for Print
define Epsilon = 1e-6;
real A, B, H, N2, R, U, V, S(2), B2;
int K, K2, M, N;
[Print("From the definition, error 3e-10\n");
N:= 400; H:= 1.;
for K:= 2 to N do
H:= H + 1.0/float(K);
\Faster convergence: Negoi, 1997
A:= Ln(float(N) + 0.5 + 1.0/(24.*float(N)));
Print("Hn %1.16f\n", H);
Print("gamma %1.16f\nK = %d\n\n", H-A, N);
Print("Sweeney, 1963, error 3e-10\n");
N:= 21; S(0):= 0.; S(1):= float(N);
R:= float(N); K:= 1;
repeat
K:= K+1;
R:= R * float(N) / float(K);
S(K&1):= S(K&1) + R/float(K);
until R <= Epsilon;
Print("gamma %1.16f\nK = %d\n\n", S(1)-S(0)-Ln(float(N)), K);
Print("Bailey, 1988\n");
N:= 5; A:= 1.; H:= 1.;
N2:= Pow(2., float(N));
R:= 1.; K:= 1;
repeat
K:= K+1;
R:= R * N2 / float(K);
H:= H + 1.0/float(K);
B:= A; A:= A + R*H;
until abs(B-A) <= Epsilon;
A:= A * N2 / Exp(N2);
Print("gamma %1.16f\nK = %d\n\n", A-float(N)*Ln(2.), K);
Print("Brent-McMillan, 1980\n");
N:= 13; A:= -Ln(float(N));
B:= 1.; U:= A; V:= B;
N2:= float(N*N); K2:= 0; K:= 0;
repeat
K2:= K2 + 2*K + 1;
K:= K+1;
A:= A * N2 / float(K);
B:= B * N2 / float(K2);
A:= (A + B) / float(K);
U:= U + A;
V:= V + B;
until abs(A) <= Epsilon;
Print("gamma %1.16f\nK = %d\n\n", U/V, K);
Print("How Euler did it in 1735\n");
\Bernoulli numbers with even indices
B2:= [1.0, 1.0/6., -1.0/30., 1.0/42., -1.0/30.,
5.0/66., -691.0/2730., 7.0/6., -3617.0/510., 43867.0/798.];
M:= 7; N:= 10;
\Nth harmonic number
H:= 1.;
for K:= 2 to N do
H:= H + 1.0/float(K);
Print("Hn %1.16f\n", H);
H:= H - Ln(float(N));
Print(" -ln %1.16f\n", H);
\Expansion C:= -digamma(1)
A:= -1.0 / (2.*float(N));
N2:= float(N*N);
R:= 1.;
for K:= 1 to M do [
R:= R * N2;
A:= A + B2(K)/(2.*float(K)*R);
];
Print("err %1.16f\ngamma %1.16f\nK = %d", A, H+A, N+M);
Print("\n\nC = 0.57721566490153286...\n");
]
- Output:
From the definition, error 3e-10 Hn 6.5699296911765100 gamma 0.5772156645765730 K = 400 Sweeney, 1963, error 3e-10 gamma 0.5772156645636310 K = 68 Bailey, 1988 gamma 0.5772156649015350 K = 89 Brent-McMillan, 1980 gamma 0.5772156649015330 K = 40 How Euler did it in 1735 Hn 2.9289682539682500 -ln 0.6263831609742080 err -0.0491674960726750 gamma 0.5772156649015330 K = 17 C = 0.57721566490153286...