Java Temurin #1 — Pi Digits
Generate the digits of π with arbitrary-precision arithmetic and the step-by-step spigot algorithm.
| Time | 4,447.7 ms |
|---|---|
| CPU time | 5,012.4 ms |
| Peak memory | 487,020 KB |
| gz | 855 bytes — comments removed, gzipped |
| Style | ★★★★☆ |
| Implementation | Java — Java (Temurin) 21.0.8 |
| By | sysop- |
| Submitted | September 24, 2026 |
Style assessment
This is the canonical Benchmarks Game spigot implementation: clean camelCase naming, proper use of java.math.BigInteger for the linear-fractional transformations, and a tidy three-class decomposition (driver, spigot, transformation). What keeps it from 5: the lowercase `pidigits` class name deviates from Java convention (PiDigits/PiDigits.java is natural), the mutate-and-return-`this` reuse of `x`/`inverse`/`qrst` is unidiomatic Java that obscures data flow, digit-by-digit `System.out.print` ignores buffered output, and `String args[]` is the old-style declaration; a StringBuilder/BufferedWriter and clearer object lifecycle would raise it.
Source
128 lines · Download pidigits-java-temurin-1.java
// Preferred filename: pidigits.java -- javac requires a public class to match the filename.
/* The Computer Language Benchmarks Game
http://benchmarksgame.alioth.debian.org/
contributed by Isaac Gouy
*/
import java.math.BigInteger;
public class pidigits {
static final int L = 10;
public static void main(String args[]) {
int n = Integer.parseInt(args[0]);
int j = 0;
PiDigitSpigot digits = new PiDigitSpigot();
while (n > 0){
if (n >= L){
for (int i=0; i<L; i++) System.out.print( digits.next() );
j += L;
} else {
for (int i=0; i<n; i++) System.out.print( digits.next() );
for (int i=n; i<L; i++) System.out.print(" ");
j += n;
}
System.out.print("\t:"); System.out.println(j);
n -= L;
}
}
}
class PiDigitSpigot {
Transformation z, x, inverse;
public PiDigitSpigot(){
z = new Transformation(1,0,0,1);
x = new Transformation(0,0,0,0);
inverse = new Transformation(0,0,0,0);
}
public int next(){
int y = digit();
if (isSafe(y)){
z = produce(y); return y;
} else {
z = consume( x.next() ); return next();
}
}
public int digit(){
return z.extract(3);
}
public boolean isSafe(int digit){
return digit == z.extract(4);
}
public Transformation produce(int i){
return ( inverse.qrst(10,-10*i,0,1) ).compose(z);
}
public Transformation consume(Transformation a){
return z.compose(a);
}
}
class Transformation {
BigInteger q, r, s, t;
int k;
public Transformation(int q, int r, int s, int t){
this.q = BigInteger.valueOf(q);
this.r = BigInteger.valueOf(r);
this.s = BigInteger.valueOf(s);
this.t = BigInteger.valueOf(t);
k = 0;
}
public Transformation(BigInteger q, BigInteger r, BigInteger s, BigInteger t){
this.q = q;
this.r = r;
this.s = s;
this.t = t;
k = 0;
}
public Transformation next(){
k++;
q = BigInteger.valueOf(k);
r = BigInteger.valueOf(4 * k + 2);
s = BigInteger.valueOf(0);
t = BigInteger.valueOf(2 * k + 1);
return this;
}
public int extract(int j){
BigInteger bigj = BigInteger.valueOf(j);
BigInteger numerator = (q.multiply(bigj)).add(r);
BigInteger denominator = (s.multiply(bigj)).add(t);
return ( numerator.divide(denominator) ).intValue();
}
public Transformation qrst(int q, int r, int s, int t){
this.q = BigInteger.valueOf(q);
this.r = BigInteger.valueOf(r);
this.s = BigInteger.valueOf(s);
this.t = BigInteger.valueOf(t);
k = 0;
return this;
}
public Transformation compose(Transformation a){
return new Transformation(
q.multiply(a.q)
,(q.multiply(a.r)).add( (r.multiply(a.t)) )
,(s.multiply(a.q)).add( (t.multiply(a.s)) )
,(s.multiply(a.r)).add( (t.multiply(a.t)) )
);
}
}