Task: Faulhaber's triangle


C++: #include <exception>
#include <iomanip>
#include <iostream>
#include <numeric>
#include <sstream>
#include <vector>
 
class Frac {
public:

	Frac() : num(0), denom(1) {}

	Frac(int n, int d) {
		if (d == 0) {
			throw std::runtime_error("d must not be zero");
		}

		int sign_of_d = d < 0 ? -1 : 1;
		int g = std::gcd(n, d);

        num = sign_of_d * n / g;
        denom = sign_of_d * d / g;
	}
 
	Frac operator-() const {
		return Frac(-num, denom);
	}
 
	Frac operator+(const Frac& rhs) const {
		return Frac(num*rhs.denom + denom * rhs.num, rhs.denom*denom);
	}
 
	Frac operator-(const Frac& rhs) const {
		return Frac(num*rhs.denom - denom * rhs.num, rhs.denom*denom);
	}
 
	Frac operator*(const Frac& rhs) const {
		return Frac(num*rhs.num, denom*rhs.denom);
	}

	Frac operator*(int rhs) const {
		return Frac(num * rhs, denom);
	}

	friend std::ostream& operator<<(std::ostream&, const Frac&);
 
private:
	int num;
	int denom;
};
 
std::ostream & operator<<(std::ostream & os, const Frac &f) {
	if (f.num == 0 || f.denom == 1) {
		return os << f.num;
	}
 
	std::stringstream ss;
	ss << f.num << "/" << f.denom;
	return os << ss.str();
}
 
Frac bernoulli(int n) {
	if (n < 0) {
		throw std::runtime_error("n may not be negative or zero");
	}
 
	std::vector<Frac> a;
	for (int m = 0; m <= n; m++) {
		a.push_back(Frac(1, m + 1));
		for (int j = m; j >= 1; j--) {
			a[j - 1] = (a[j - 1] - a[j]) * j;
		}
	}
 
	
	if (n != 1) return a[0];
	return -a[0];
}
 
int binomial(int n, int k) {
	if (n < 0 || k < 0 || n < k) {
		throw std::runtime_error("parameters are invalid");
	}
	if (n == 0 || k == 0) return 1;
 
	int num = 1;
	for (int i = k + 1; i <= n; i++) {
		num *= i;
	}
 
	int denom = 1;
	for (int i = 2; i <= n - k; i++) {
		denom *= i;
	}
 
	return num / denom;
}
 
std::vector<Frac> faulhaberTraingle(int p) {
	std::vector<Frac> coeffs(p + 1);
 
	Frac q{ 1, p + 1 };
	int sign = -1;
	for (int j = 0; j <= p; j++) {
		sign *= -1;
		coeffs[p - j] = q * sign * binomial(p + 1, j) * bernoulli(j);
	}
 
	return coeffs;
}
 
int main() {
 
	for (int i = 0; i < 10; i++) {
		std::vector<Frac> coeffs = faulhaberTraingle(i);
		for (auto frac : coeffs) {
			std::cout << std::right << std::setw(5) << frac << "  ";
		}
		std::cout << std::endl;
	}
 
	return 0;
}



Go: package main

import (
    "fmt"
    "math/big"
)

func bernoulli(n uint) *big.Rat {
    a := make([]big.Rat, n+1)
    z := new(big.Rat)
    for m := range a {
        a[m].SetFrac64(1, int64(m+1))
        for j := m; j >= 1; j-- {
            d := &a[j-1]
            d.Mul(z.SetInt64(int64(j)), d.Sub(d, &a[j]))
        }
    }
    
    if n != 1 {
        return &a[0]
    }
    a[0].Neg(&a[0])
    return &a[0]
}

func binomial(n, k int) int64 {
    if n <= 0 || k <= 0 || n < k {
        return 1
    }
    var num, den int64 = 1, 1
    for i := k + 1; i <= n; i++ {
        num *= int64(i)
    }
    for i := 2; i <= n-k; i++ {
        den *= int64(i)
    }
    return num / den
}

func faulhaberTriangle(p int) []big.Rat {
    coeffs := make([]big.Rat, p+1)
    q := big.NewRat(1, int64(p)+1)
    t := new(big.Rat)
    u := new(big.Rat)
    sign := -1
    for j := range coeffs {
        sign *= -1
        d := &coeffs[p-j]
        t.SetInt64(int64(sign))
        u.SetInt64(binomial(p+1, j))
        d.Mul(q, t)
        d.Mul(d, u)
        d.Mul(d, bernoulli(uint(j)))
    }
    return coeffs
}

func main() {
    for i := 0; i < 10; i++ {
        coeffs := faulhaberTriangle(i)
        for _, coeff := range coeffs {
            fmt.Printf("%5s  ", coeff.RatString())
        }
        fmt.Println()
    }
    fmt.Println()
    
    k := 17
    cc := faulhaberTriangle(k)
    n := int64(1000)
    nn := big.NewRat(n, 1)
    np := big.NewRat(1, 1)
    sum := new(big.Rat)
    tmp := new(big.Rat)
    for _, c := range cc {
        np.Mul(np, nn)
        tmp.Set(np)
        tmp.Mul(tmp, &c)
        sum.Add(sum, tmp)
    }
    fmt.Println(sum.RatString())
}