Ramanujan's constant: Difference between revisions
(Added Perl) |
(Added Go) |
||
Line 5: | Line 5: | ||
show that when evaulated with the last four [https://en.wikipedia.org/wiki/Heegner_number Heegner numbers] |
show that when evaulated with the last four [https://en.wikipedia.org/wiki/Heegner_number Heegner numbers] |
||
the result is ''almost'' an integer. |
the result is ''almost'' an integer. |
||
=={{header|Go}}== |
|||
{{libheader|bigfloat}} |
|||
The standard library's math/big.Float type lacks an exponentiation function and so I have had to use an external library to provide this function. |
|||
Also the math.Pi built in constant is not accurate enough to be used with big.Float and so I have used a more accurate string representation instead. |
|||
<lang go>package main |
|||
import ( |
|||
"fmt" |
|||
"github.com/ALTree/bigfloat" |
|||
"math/big" |
|||
) |
|||
const ( |
|||
prec = 256 // say |
|||
ps = "3.1415926535897932384626433832795028841971693993751058209749445923078164" |
|||
) |
|||
func q(d int64) *big.Float { |
|||
pi, _ := new(big.Float).SetPrec(prec).SetString(ps) |
|||
t := new(big.Float).SetPrec(prec).SetInt64(d) |
|||
t.Sqrt(t) |
|||
t.Mul(pi, t) |
|||
return bigfloat.Exp(t) |
|||
} |
|||
func main() { |
|||
fmt.Println("Ramanujan's constant to 32 decimal places is:") |
|||
fmt.Printf("%.32f\n", q(163)) |
|||
heegners := [4][2]int64{ |
|||
{19, 96}, |
|||
{43, 960}, |
|||
{67, 5280}, |
|||
{163, 640320}, |
|||
} |
|||
fmt.Println("\nHeegner numbers yielding 'almost' integers:") |
|||
t := new(big.Float).SetPrec(prec) |
|||
for _, h := range heegners { |
|||
qh := q(h[0]) |
|||
c := h[1]*h[1]*h[1] + 744 |
|||
t.SetInt64(c) |
|||
t.Sub(t, qh) |
|||
fmt.Printf("%3d: %51.32f ≈ %18d (diff: %.32f)\n", h[0], qh, c, t) |
|||
} |
|||
}</lang> |
|||
{{out}} |
|||
<pre> |
|||
Ramanujan's constant to 32 decimal places is: |
|||
262537412640768743.99999999999925007259719818568888 |
|||
Heegner numbers yielding 'almost' integers: |
|||
19: 885479.77768015431949753789348171962682 ≈ 885480 (diff: 0.22231984568050246210651828037318) |
|||
43: 884736743.99977746603490666193746207858538 ≈ 884736744 (diff: 0.00022253396509333806253792141462) |
|||
67: 147197952743.99999866245422450682926131257863 ≈ 147197952744 (diff: 0.00000133754577549317073868742137) |
|||
163: 262537412640768743.99999999999925007259719818568888 ≈ 262537412640768744 (diff: 0.00000000000074992740280181431112) |
|||
</pre> |
|||
=={{header|Perl}}== |
=={{header|Perl}}== |
Revision as of 11:39, 25 April 2019
Calculate Ramanujan's constant (as described on the OEIS site) with at least 32 digits of precision, by the method of your choice. Optionally, if using the 𝑒**(π*√x) approach, show that when evaulated with the last four Heegner numbers the result is almost an integer.
Go
The standard library's math/big.Float type lacks an exponentiation function and so I have had to use an external library to provide this function.
Also the math.Pi built in constant is not accurate enough to be used with big.Float and so I have used a more accurate string representation instead. <lang go>package main
import (
"fmt" "github.com/ALTree/bigfloat" "math/big"
)
const (
prec = 256 // say ps = "3.1415926535897932384626433832795028841971693993751058209749445923078164"
)
func q(d int64) *big.Float {
pi, _ := new(big.Float).SetPrec(prec).SetString(ps) t := new(big.Float).SetPrec(prec).SetInt64(d) t.Sqrt(t) t.Mul(pi, t) return bigfloat.Exp(t)
}
func main() {
fmt.Println("Ramanujan's constant to 32 decimal places is:") fmt.Printf("%.32f\n", q(163)) heegners := [4][2]int64{ {19, 96}, {43, 960}, {67, 5280}, {163, 640320}, } fmt.Println("\nHeegner numbers yielding 'almost' integers:") t := new(big.Float).SetPrec(prec) for _, h := range heegners { qh := q(h[0]) c := h[1]*h[1]*h[1] + 744 t.SetInt64(c) t.Sub(t, qh) fmt.Printf("%3d: %51.32f ≈ %18d (diff: %.32f)\n", h[0], qh, c, t) }
}</lang>
- Output:
Ramanujan's constant to 32 decimal places is: 262537412640768743.99999999999925007259719818568888 Heegner numbers yielding 'almost' integers: 19: 885479.77768015431949753789348171962682 ≈ 885480 (diff: 0.22231984568050246210651828037318) 43: 884736743.99977746603490666193746207858538 ≈ 884736744 (diff: 0.00022253396509333806253792141462) 67: 147197952743.99999866245422450682926131257863 ≈ 147197952744 (diff: 0.00000133754577549317073868742137) 163: 262537412640768743.99999999999925007259719818568888 ≈ 262537412640768744 (diff: 0.00000000000074992740280181431112)
Perl
<lang perl>use strict; use warnings; use Math::AnyNum;
sub ramanujan_const {
my ($x, $decimals) = @_;
$x = Math::AnyNum->new($x); my $prec = 4 * ((Math::AnyNum->pi * $x->sqrt) / log(2) + $decimals); local $Math::AnyNum::PREC = $prec->round->numify;
my $e = Math::AnyNum->e; my $pi = Math::AnyNum->pi; my $c = $e**($pi * $x->sqrt); $c->round(-$decimals)->stringify;
}
my $decimals = 100; printf("Ramanujan's constant to $decimals decimals:\n%s\n\n",
ramanujan_const(163, $decimals));
print "Heegner numbers yielding 'almost' integers:\n"; my @tests = (19, 96, 43, 960, 67, 5280, 163, 640320);
while (@tests) {
my ($h, $x) = splice(@tests, 0, 2); my $c = ramanujan_const($h, 32); my $n = Math::AnyNum::ipow($x, 3) + 744; printf("%3s: %51s ≈ %18s (diff: %s)\n", $h, $c, $n, ($n - $c)->round(-32));
}</lang>
- Output:
Ramanujan's constant to 100 decimals: 262537412640768743.9999999999992500725971981856888793538563373369908627075374103782106479101186073129511813461860645042 Heegner numbers yielding 'almost' integers: 19: 885479.77768015431949753789348171962682 ≈ 885480 (diff: 0.22231984568050246210651828037318) 43: 884736743.99977746603490666193746207858538 ≈ 884736744 (diff: 0.00022253396509333806253792141462) 67: 147197952743.99999866245422450682926131257863 ≈ 147197952744 (diff: 0.00000133754577549317073868742137) 163: 262537412640768743.99999999999925007259719818568888 ≈ 262537412640768744 (diff: 0.00000000000074992740280181431112)
Perl 6
To generate a high-precision value for Ramanujan's constant, code is borrowed from three other Rosettacode tasks (with some modifications) for performing calculations of the value of π, Euler's number, and integer roots. Additional custom routines for exponentiation are used to ensure all computations are done with rationals, specifically FatRats (rational numbers stored with arbitrary size numerator and denominator). The module Rat::Precise makes it simple to display these to a configurable precision. <lang perl6>use Rat::Precise;
- set the degree of precision for calculations
constant D = 54; constant d = 15;
- two versions of exponentiation where base and exponent are both FatRat
multi infix:<**> (FatRat $base, FatRat $exp where * >= 1 --> FatRat) {
2 R** $base**($exp/2);
}
multi infix:<**> (FatRat $base, FatRat $exp where * < 1 --> FatRat) {
constant ε = 10**-D; my $low = 0.FatRat; my $high = 1.FatRat; my $mid = $high / 2; my $acc = my $sqr = sqrt($base);
while (abs($mid - $exp) > ε) { $sqr = sqrt($sqr); if ($mid <= $exp) { $low = $mid; $acc *= $sqr } else { $high = $mid; $acc *= 1/$sqr } $mid = ($low + $high) / 2; } $acc.substr(0, D).FatRat;
}
- calculation of π
sub π (--> FatRat) {
my ($a, $n) = 1, 1; my $g = sqrt 1/2.FatRat; my $z = .25; my $pi;
for ^d { given [ ($a + $g)/2, sqrt $a * $g ] { $z -= (.[0] - $a)**2 * $n; $n += $n; ($a, $g) = @$_; $pi = ($a ** 2 / $z).substr: 0, 2 + D; } } $pi.FatRat;
}
multi sqrt(FatRat $r --> FatRat) {
FatRat.new: sqrt($r.nude[0] * 10**(D*2) div $r.nude[1]), 10**D;
}
- integer roots
multi sqrt(Int $n) {
my $guess = 10**($n.chars div 2); my $iterator = { ( $^x + $n div ($^x) ) div 2 }; my $endpoint = { $^x == $^y|$^z }; min ($guess, $iterator … $endpoint)[*-1, *-2];
}
- 'cosmetic' cover to upgrade input to FatRat sqrt
sub prefix:<√> (Int $n) { sqrt($n.FatRat) }
- calculation of 𝑒
sub postfix:<!> (Int $n) { (constant f = 1, |[\*] 1..*)[$n] } sub 𝑒 (--> FatRat) { sum map { FatRat.new(1,.!) }, ^D }
- inputs, and their difference, formatted decimal-aligned
sub format ($a,$b) {
sub pad ($s) { ' ' x ((34 - d - 1) - ($s.split(/\./)[0]).chars) } my $c = $b.precise(d, :z); my $d = ($a-$b).precise(d, :z); join "\n", (sprintf "%11s {pad($a)}%s\n", 'Int', $a) ~ (sprintf "%11s {pad($c)}%s\n", 'Heegner', $c) ~ (sprintf "%11s {pad($d)}%s\n", 'Difference', $d)
}
- override built-in definitions
constant π = &π(); constant 𝑒 = &𝑒();
my $Ramanujan = 𝑒**(π*√163); say "Ramanujan's constant to 32 decimal places:\nActual: " ~
"262537412640768743.99999999999925007259719818568888\n" ~ "Calculated: ", $Ramanujan.precise(32, :z), "\n";
say "Heegner numbers yielding 'almost' integers"; for 19, 96, 43, 960, 67, 5280, 163, 640320 -> $heegner, $x {
my $almost = 𝑒**(π*√$heegner); my $exact = $x**3 + 744; say format($exact, $almost);
}</lang>
- Output:
Ramanujan's constant to 32 decimal places: Actual: 262537412640768743.99999999999925007259719818568888 Calculated: 262537412640768743.99999999999925007259719818568888 Heegner numbers yielding 'almost' integers Int 885480 Heegner 885479.777680154319498 Difference 0.222319845680502 Int 884736744 Heegner 884736743.999777466034907 Difference 0.000222533965093 Int 147197952744 Heegner 147197952743.999998662454225 Difference 0.000001337545775 Int 262537412640768744 Heegner 262537412640768743.999999999999250 Difference 0.000000000000750
Sidef
<lang ruby>func ramanujan_const(x, decimals=32) {
local Num!PREC = *"#{4*round((Num.pi*√x)/log(2) + decimals)}" Num.e**(Num.pi * √x) -> round(-decimals).to_s
}
var decimals = 100 printf("Ramanujan's constant to #{decimals} decimals:\n%s\n\n",
ramanujan_const(163, decimals))
say "Heegner numbers yielding 'almost' integers:" [19, 96, 43, 960, 67, 5280, 163, 640320].each_slice(2, {|h,x|
var c = ramanujan_const(h, 32) var n = (x**3 + 744) printf("%3s: %51s ≈ %18s (diff: %s)\n", h, c, n, n-Num(c))
})</lang>
- Output:
Ramanujan's constant to 100 decimals: 262537412640768743.9999999999992500725971981856888793538563373369908627075374103782106479101186073129511813461860645042 Heegner numbers yielding 'almost' integers: 19: 885479.77768015431949753789348171962682 ≈ 885480 (diff: 0.22231984568050246210651828037318) 43: 884736743.99977746603490666193746207858538 ≈ 884736744 (diff: 0.00022253396509333806253792141462) 67: 147197952743.99999866245422450682926131257863 ≈ 147197952744 (diff: 0.00000133754577549317073868742137) 163: 262537412640768743.99999999999925007259719818568888 ≈ 262537412640768744 (diff: 0.00000000000074992740280181431112)