Data commit

This commit is contained in:
Ingy döt Net 2023-07-01 11:58:00 -04:00
parent 7387c8f97b
commit cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions

View file

@ -0,0 +1,3 @@
---
from: http://rosettacode.org/wiki/Faulhaber's_triangle
note: Mathematics

View file

@ -0,0 +1,37 @@
Named after [https://en.wikipedia.org/wiki/Johann_Faulhaber Johann Faulhaber], the rows of Faulhaber's triangle are the coefficients of polynomials that represent sums of integer powers, which are extracted from Faulhaber's formula:
:<math>\sum_{k=1}^n k^p = {1 \over p+1} \sum_{j=0}^p {p+1 \choose j} B_j n^{p+1-j}</math>
where <math>B_n</math> is the nth-Bernoulli number.
The first 5 rows of Faulhaber's triangle, are:
<pre>
1
1/2 1/2
1/6 1/2 1/3
0 1/4 1/2 1/4
-1/30 0 1/3 1/2 1/5
</pre>
Using the third row of the triangle, we have:
<math>\sum_{k=1}^n k^2 = {1 \over 6} n + {1 \over 2} n^2 + {1 \over 3} n^3</math>
; Task
:* show the first 10 rows of Faulhaber's triangle.
:* using the 18th row of Faulhaber's triangle, compute the sum: <math>\sum_{k=1}^{1000} k^{17}</math> (extra credit).
; See also:
* [[Bernoulli numbers]]
* [[Evaluate binomial coefficients]]
* [https://en.wikipedia.org/wiki/Faulhaber%27s_formula Faulhaber's formula (Wikipedia)]
* [http://www.ww.ingeniousmathstat.org/sites/default/files/Torabi-Dashti-CMJ-2011.pdf Faulhaber's triangle (PDF)]
<br>

View file

@ -0,0 +1,123 @@
#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;
}
}
// returns 'first' Bernoulli number
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;
}

View file

@ -0,0 +1,155 @@
using System;
namespace FaulhabersTriangle {
internal class Frac {
private long num;
private long denom;
public static readonly Frac ZERO = new Frac(0, 1);
public static readonly Frac ONE = new Frac(1, 1);
public Frac(long n, long d) {
if (d == 0) {
throw new ArgumentException("d must not be zero");
}
long nn = n;
long dd = d;
if (nn == 0) {
dd = 1;
}
else if (dd < 0) {
nn = -nn;
dd = -dd;
}
long g = Math.Abs(Gcd(nn, dd));
if (g > 1) {
nn /= g;
dd /= g;
}
num = nn;
denom = dd;
}
private static long Gcd(long a, long b) {
if (b == 0) {
return a;
}
return Gcd(b, a % b);
}
public static Frac operator -(Frac self) {
return new Frac(-self.num, self.denom);
}
public static Frac operator +(Frac lhs, Frac rhs) {
return new Frac(lhs.num * rhs.denom + lhs.denom * rhs.num, rhs.denom * lhs.denom);
}
public static Frac operator -(Frac lhs, Frac rhs) {
return lhs + -rhs;
}
public static Frac operator *(Frac lhs, Frac rhs) {
return new Frac(lhs.num * rhs.num, lhs.denom * rhs.denom);
}
public static bool operator <(Frac lhs, Frac rhs) {
double x = (double)lhs.num / lhs.denom;
double y = (double)rhs.num / rhs.denom;
return x < y;
}
public static bool operator >(Frac lhs, Frac rhs) {
double x = (double)lhs.num / lhs.denom;
double y = (double)rhs.num / rhs.denom;
return x > y;
}
public static bool operator ==(Frac lhs, Frac rhs) {
return lhs.num == rhs.num && lhs.denom == rhs.denom;
}
public static bool operator !=(Frac lhs, Frac rhs) {
return lhs.num != rhs.num || lhs.denom != rhs.denom;
}
public override string ToString() {
if (denom == 1) {
return num.ToString();
}
return string.Format("{0}/{1}", num, denom);
}
public override bool Equals(object obj) {
var frac = obj as Frac;
return frac != null &&
num == frac.num &&
denom == frac.denom;
}
public override int GetHashCode() {
var hashCode = 1317992671;
hashCode = hashCode * -1521134295 + num.GetHashCode();
hashCode = hashCode * -1521134295 + denom.GetHashCode();
return hashCode;
}
}
class Program {
static Frac Bernoulli(int n) {
if (n < 0) {
throw new ArgumentException("n may not be negative or zero");
}
Frac[] a = new Frac[n + 1];
for (int m = 0; m <= n; m++) {
a[m] = new Frac(1, m + 1);
for (int j = m; j >= 1; j--) {
a[j - 1] = (a[j - 1] - a[j]) * new Frac(j, 1);
}
}
// returns 'first' Bernoulli number
if (n != 1) return a[0];
return -a[0];
}
static int Binomial(int n, int k) {
if (n < 0 || k < 0 || n < k) {
throw new ArgumentException();
}
if (n == 0 || k == 0) return 1;
int num = 1;
for (int i = k + 1; i <= n; i++) {
num = num * i;
}
int denom = 1;
for (int i = 2; i <= n - k; i++) {
denom = denom * i;
}
return num / denom;
}
static Frac[] FaulhaberTriangle(int p) {
Frac[] coeffs = new Frac[p + 1];
for (int i = 0; i < p + 1; i++) {
coeffs[i] = Frac.ZERO;
}
Frac q = new Frac(1, p + 1);
int sign = -1;
for (int j = 0; j <= p; j++) {
sign *= -1;
coeffs[p - j] = q * new Frac(sign, 1) * new Frac(Binomial(p + 1, j), 1) * Bernoulli(j);
}
return coeffs;
}
static void Main(string[] args) {
for (int i = 0; i < 10; i++) {
Frac[] coeffs = FaulhaberTriangle(i);
foreach (Frac coeff in coeffs) {
Console.Write("{0,5} ", coeff);
}
Console.WriteLine();
}
}
}
}

View file

@ -0,0 +1,158 @@
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int binomial(int n, int k) {
int num, denom, i;
if (n < 0 || k < 0 || n < k) return -1;
if (n == 0 || k == 0) return 1;
num = 1;
for (i = k + 1; i <= n; ++i) {
num = num * i;
}
denom = 1;
for (i = 2; i <= n - k; ++i) {
denom *= i;
}
return num / denom;
}
int gcd(int a, int b) {
int temp;
while (b != 0) {
temp = a % b;
a = b;
b = temp;
}
return a;
}
typedef struct tFrac {
int num, denom;
} Frac;
Frac makeFrac(int n, int d) {
Frac result;
int g;
if (d == 0) {
result.num = 0;
result.denom = 0;
return result;
}
if (n == 0) {
d = 1;
} else if (d < 0) {
n = -n;
d = -d;
}
g = abs(gcd(n, d));
if (g > 1) {
n = n / g;
d = d / g;
}
result.num = n;
result.denom = d;
return result;
}
Frac negateFrac(Frac f) {
return makeFrac(-f.num, f.denom);
}
Frac subFrac(Frac lhs, Frac rhs) {
return makeFrac(lhs.num * rhs.denom - lhs.denom * rhs.num, rhs.denom * lhs.denom);
}
Frac multFrac(Frac lhs, Frac rhs) {
return makeFrac(lhs.num * rhs.num, lhs.denom * rhs.denom);
}
bool equalFrac(Frac lhs, Frac rhs) {
return (lhs.num == rhs.num) && (lhs.denom == rhs.denom);
}
bool lessFrac(Frac lhs, Frac rhs) {
return (lhs.num * rhs.denom) < (rhs.num * lhs.denom);
}
void printFrac(Frac f) {
char buffer[7];
int len;
if (f.denom != 1) {
snprintf(buffer, 7, "%d/%d", f.num, f.denom);
} else {
snprintf(buffer, 7, "%d", f.num);
}
len = 7 - strlen(buffer);
while (len-- > 0) {
putc(' ', stdout);
}
printf(buffer);
}
Frac bernoulli(int n) {
Frac a[16];
int j, m;
if (n < 0) {
a[0].num = 0;
a[0].denom = 0;
return a[0];
}
for (m = 0; m <= n; ++m) {
a[m] = makeFrac(1, m + 1);
for (j = m; j >= 1; --j) {
a[j - 1] = multFrac(subFrac(a[j - 1], a[j]), makeFrac(j, 1));
}
}
if (n != 1) {
return a[0];
}
return negateFrac(a[0]);
}
void faulhaber(int p) {
Frac q, *coeffs;
int j, sign;
coeffs = malloc(sizeof(Frac)*(p + 1));
q = makeFrac(1, p + 1);
sign = -1;
for (j = 0; j <= p; ++j) {
sign = -1 * sign;
coeffs[p - j] = multFrac(multFrac(multFrac(q, makeFrac(sign, 1)), makeFrac(binomial(p + 1, j), 1)), bernoulli(j));
}
for (j = 0; j <= p; ++j) {
printFrac(coeffs[j]);
}
printf("\n");
free(coeffs);
}
int main() {
int i;
for (i = 0; i < 10; ++i) {
faulhaber(i);
}
return 0;
}

View file

@ -0,0 +1,134 @@
import std.algorithm : fold;
import std.conv : to;
import std.exception : enforce;
import std.format : formattedWrite;
import std.numeric : cmp, gcd;
import std.range : iota;
import std.stdio;
import std.traits;
auto abs(T)(T val)
if (isNumeric!T) {
if (val < 0) {
return -val;
}
return val;
}
struct Frac {
long num;
long denom;
enum ZERO = Frac(0, 1);
enum ONE = Frac(1, 1);
this(long n, long d) in {
enforce(d != 0, "Parameter d may not be zero.");
} body {
auto nn = n;
auto dd = d;
if (nn == 0) {
dd = 1;
} else if (dd < 0) {
nn = -nn;
dd = -dd;
}
auto g = gcd(abs(nn), abs(dd));
if (g > 1) {
nn /= g;
dd /= g;
}
num = nn;
denom = dd;
}
auto opBinary(string op)(Frac rhs) const {
static if (op == "+" || op == "-") {
return mixin("Frac(num*rhs.denom"~op~"denom*rhs.num, rhs.denom*denom)");
} else if (op == "*") {
return Frac(num*rhs.num, denom*rhs.denom);
}
}
auto opUnary(string op : "-")() const {
return Frac(-num, denom);
}
int opCmp(Frac rhs) const {
return cmp(cast(real) this, cast(real) rhs);
}
bool opEquals(Frac rhs) const {
return num == rhs.num && denom == rhs.denom;
}
void toString(scope void delegate(const(char)[]) sink) const {
if (denom == 1) {
formattedWrite(sink, "%d", num);
} else {
formattedWrite(sink, "%d/%s", num, denom);
}
}
T opCast(T)() const if (isFloatingPoint!T) {
return cast(T) num / denom;
}
}
auto abs(Frac f) {
if (f.num >= 0) {
return f;
}
return -f;
}
auto bernoulli(int n) in {
enforce(n >= 0, "Parameter n must not be negative.");
} body {
Frac[] a;
a.length = n+1;
a[0] = Frac.ZERO;
foreach (m; 0..n+1) {
a[m] = Frac(1, m+1);
foreach_reverse (j; 1..m+1) {
a[j-1] = (a[j-1] - a[j]) * Frac(j, 1);
}
}
if (n != 1) {
return a[0];
}
return -a[0];
}
auto binomial(int n, int k) in {
enforce(n>=0 && k>=0 && n>=k);
} body {
if (n==0 || k==0) return 1;
auto num = iota(k+1, n+1).fold!"a*b"(1);
auto den = iota(2, n-k+1).fold!"a*b"(1);
return num / den;
}
Frac[] faulhaberTriangle(int p) {
Frac[] coeffs;
coeffs.length = p+1;
coeffs[0] = Frac.ZERO;
auto q = Frac(1, p+1);
auto sign = -1;
foreach (j; 0..p+1) {
sign *= -1;
coeffs[p - j] = q * Frac(sign, 1) * Frac(binomial(p+1, j), 1) * bernoulli(j);
}
return coeffs;
}
void main() {
foreach (i; 0..10) {
auto coeffs = faulhaberTriangle(i);
foreach (coeff; coeffs) {
writef("%5s ", coeff.to!string);
}
writeln;
}
writeln;
}

View file

@ -0,0 +1,6 @@
// Generate Faulhaber's Triangle. Nigel Galloway: May 8th., 2018
let Faulhaber=let fN n = (1N - List.sum n)::n
let rec Faul a b=seq{let t = fN (List.mapi(fun n g->b*g/BigRational.FromInt(n+2)) a)
yield t
yield! Faul t (b+1N)}
Faul [] 0N

View file

@ -0,0 +1 @@
Faulhaber |> Seq.take 10 |> Seq.iter (printfn "%A")

View file

@ -0,0 +1,8 @@
USING: kernel math math.combinatorics math.extras math.functions
math.ranges prettyprint sequences ;
: faulhaber ( p -- seq )
1 + dup recip swap dup 0 (a,b]
[ [ nCk ] [ -1 swap ^ ] [ bernoulli ] tri * * * ] 2with map ;
10 [ faulhaber . ] each-integer

View file

@ -0,0 +1,88 @@
' version 12-08-2017
' compile with: fbc -s console
' uses GMP
#Include Once "gmp.bi"
#Define i_max 17
Dim As UInteger i, j, x
Dim As String s
Dim As ZString Ptr gmp_str : gmp_str = Allocate(100)
Dim As Mpq_ptr n, tmp1, tmp2, sum, one, zero
n = Allocate(Len(__mpq_struct)) : Mpq_init(n)
tmp1 = Allocate(Len(__mpq_struct)) : Mpq_init(tmp1)
tmp2 = Allocate(Len(__mpq_struct)) : Mpq_init(tmp2)
sum = Allocate(Len(__mpq_struct)) : Mpq_init(sum)
zero = Allocate(Len(__mpq_struct)) : Mpq_init(zero)
one = Allocate(Len(__mpq_struct)) : Mpq_init(one)
Mpq_set_ui(zero, 0, 0) ' 0/0 = 0
Mpq_set_ui(one , 1, 1) ' 1/1 = 1
Dim As Mpq_ptr Faulhaber_triangle(0 To i_max, 1 To i_max +1)
' only initialize the variables we need
For i = 0 To i_max
For j = 1 To i +1
Faulhaber_triangle(i, j) = Allocate(Len(__Mpq_struct))
Mpq_init(Faulhaber_triangle(i, j))
Next
Next
Mpq_set(Faulhaber_triangle(0, 1), one)
' we calculate the first 18 rows
For i = 1 To i_max
Mpq_set(sum, zero)
For j = i +1 To 2 Step -1
Mpq_set_ui(tmp1, i, j) ' i / j
Mpq_set(tmp2, Faulhaber_triangle(i -1, j -1))
Mpq_mul(Faulhaber_triangle(i, j), tmp2, tmp1)
Mpq_canonicalize(Faulhaber_triangle(i, j))
Mpq_add(sum, sum, Faulhaber_triangle(i, j))
Next
Mpq_sub(Faulhaber_triangle(i, 1), one, sum)
Next
Print "The first 10 rows"
For i = 0 To 9
For j = 1 To i +1
Mpq_get_str(gmp_str, 10, Faulhaber_triangle(i, j))
s = Space(6) + *gmp_str + Space(6)
x = InStr(s,"/")
If x = 0 Then x = 7 ' in case of 0 or 1
Print Mid(s, x -3, 7);
Next
Print
Next
print
' using the 17'the row
Mpq_set(sum, zero)
Mpq_set_ui(n, 1000, 1) ' 1000/1 = 1000
Mpq_set(tmp2, n)
For j = 1 To 18
Mpq_mul(tmp1, n, Faulhaber_triangle(17, j))
Mpq_add(sum, sum, tmp1)
Mpq_mul(n, n, tmp2)
Next
Mpq_get_str(gmp_str, 10, sum)
Print *gmp_str
' free memory
DeAllocate(gmp_str)
Mpq_clear(tmp1) : Mpq_clear(tmp2) : Mpq_clear(n)
Mpq_clear(zero) : Mpq_clear(one) : Mpq_clear(sum)
For i = 0 To i_max
For j = 1 To i +1
Mpq_clear(Faulhaber_triangle(i, j))
Next
Next
' empty keyboard buffer
While Inkey <> "" : Wend
Print : Print "hit any key to end program"
Sleep
End

View file

@ -0,0 +1,82 @@
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]))
}
}
// return the 'first' Bernoulli number
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()
// get coeffs for (k + 1)th row
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())
}

View file

@ -0,0 +1,140 @@
import java.math.MathContext
import java.util.stream.LongStream
class FaulhabersTriangle {
private static final MathContext MC = new MathContext(256)
private static long gcd(long a, long b) {
if (b == 0) {
return a
}
return gcd(b, a % b)
}
private static class Frac implements Comparable<Frac> {
private long num
private long denom
public static final Frac ZERO = new Frac(0, 1)
Frac(long n, long d) {
if (d == 0) throw new IllegalArgumentException("d must not be zero")
long nn = n
long dd = d
if (nn == 0) {
dd = 1
} else if (dd < 0) {
nn = -nn
dd = -dd
}
long g = Math.abs(gcd(nn, dd))
if (g > 1) {
nn /= g
dd /= g
}
num = nn
denom = dd
}
Frac plus(Frac rhs) {
return new Frac(num * rhs.denom + denom * rhs.num, rhs.denom * denom)
}
Frac negative() {
return new Frac(-num, denom)
}
Frac minus(Frac rhs) {
return this + -rhs
}
Frac multiply(Frac rhs) {
return new Frac(this.num * rhs.num, this.denom * rhs.denom)
}
@Override
int compareTo(Frac o) {
double diff = toDouble() - o.toDouble()
return Double.compare(diff, 0.0)
}
@Override
boolean equals(Object obj) {
return null != obj && obj instanceof Frac && this == (Frac) obj
}
@Override
String toString() {
if (denom == 1) {
return Long.toString(num)
}
return String.format("%d/%d", num, denom)
}
double toDouble() {
return (double) num / denom
}
BigDecimal toBigDecimal() {
return BigDecimal.valueOf(num).divide(BigDecimal.valueOf(denom), MC)
}
}
private static Frac bernoulli(int n) {
if (n < 0) throw new IllegalArgumentException("n may not be negative or zero")
Frac[] a = new Frac[n + 1]
Arrays.fill(a, Frac.ZERO)
for (int m = 0; m <= n; ++m) {
a[m] = new Frac(1, m + 1)
for (int j = m; j >= 1; --j) {
a[j - 1] = (a[j - 1] - a[j]) * new Frac(j, 1)
}
}
// returns 'first' Bernoulli number
if (n != 1) return a[0]
return -a[0]
}
private static long binomial(int n, int k) {
if (n < 0 || k < 0 || n < k) throw new IllegalArgumentException()
if (n == 0 || k == 0) return 1
long num = LongStream.rangeClosed(k + 1, n).reduce(1, { a, b -> a * b })
long den = LongStream.rangeClosed(2, n - k).reduce(1, { acc, i -> acc * i })
return num / den
}
private static Frac[] faulhaberTriangle(int p) {
Frac[] coeffs = new Frac[p + 1]
Arrays.fill(coeffs, Frac.ZERO)
Frac q = new Frac(1, p + 1)
int sign = -1
for (int j = 0; j <= p; ++j) {
sign *= -1
coeffs[p - j] = q * new Frac(sign, 1) * new Frac(binomial(p + 1, j), 1) * bernoulli(j)
}
return coeffs
}
static void main(String[] args) {
for (int i = 0; i <= 9; ++i) {
Frac[] coeffs = faulhaberTriangle(i)
for (Frac coeff : coeffs) {
printf("%5s ", coeff)
}
println()
}
println()
// get coeffs for (k + 1)th row
int k = 17
Frac[] cc = faulhaberTriangle(k)
int n = 1000
BigDecimal nn = BigDecimal.valueOf(n)
BigDecimal np = BigDecimal.ONE
BigDecimal sum = BigDecimal.ZERO
for (Frac c : cc) {
np = np * nn
sum = sum.add(np * c.toBigDecimal())
}
println(sum.toBigInteger())
}
}

View file

@ -0,0 +1,73 @@
import Data.Ratio (Ratio, denominator, numerator, (%))
------------------------ FAULHABER -----------------------
faulhaber :: Int -> Rational -> Rational
faulhaber p n =
sum $
zipWith ((*) . (n ^)) [1 ..] (faulhaberTriangle !! p)
faulhaberTriangle :: [[Rational]]
faulhaberTriangle =
tail $
scanl
( \rs n ->
let xs = zipWith ((*) . (n %)) [2 ..] rs
in 1 - sum xs : xs
)
[]
[0 ..]
--------------------------- TEST -------------------------
main :: IO ()
main = do
let triangle = take 10 faulhaberTriangle
widths = maxWidths triangle
mapM_
putStrLn
[ unlines
( (justifyRatio widths 8 ' ' =<<)
<$> triangle
),
(show . numerator) (faulhaber 17 1000)
]
------------------------- DISPLAY ------------------------
justifyRatio ::
(Int, Int) -> Int -> Char -> Rational -> String
justifyRatio (wn, wd) n c nd =
go $
[numerator, denominator] <*> [nd]
where
-- Minimum column width, or more if specified.
w = max n (wn + wd + 2)
go [num, den]
| 1 == den = center w c (show num)
| otherwise =
let (q, r) = quotRem (w - 1) 2
in concat
[ justifyRight q c (show num),
"/",
justifyLeft (q + r) c (show den)
]
justifyLeft :: Int -> a -> [a] -> [a]
justifyLeft n c s = take n (s <> replicate n c)
justifyRight :: Int -> a -> [a] -> [a]
justifyRight n c = (drop . length) <*> (replicate n c <>)
center :: Int -> a -> [a] -> [a]
center n c s =
let (q, r) = quotRem (n - length s) 2
pad = replicate q c
in concat [pad, s, pad, replicate r c]
maxWidths :: [[Rational]] -> (Int, Int)
maxWidths xss =
let widest f xs = maximum $ fmap (length . show . f) xs
in ((,) . widest numerator <*> widest denominator) $
concat xss

View file

@ -0,0 +1,142 @@
import java.math.BigDecimal;
import java.math.MathContext;
import java.util.Arrays;
import java.util.stream.LongStream;
public class FaulhabersTriangle {
private static final MathContext MC = new MathContext(256);
private static long gcd(long a, long b) {
if (b == 0) {
return a;
}
return gcd(b, a % b);
}
private static class Frac implements Comparable<Frac> {
private long num;
private long denom;
public static final Frac ZERO = new Frac(0, 1);
public Frac(long n, long d) {
if (d == 0) throw new IllegalArgumentException("d must not be zero");
long nn = n;
long dd = d;
if (nn == 0) {
dd = 1;
} else if (dd < 0) {
nn = -nn;
dd = -dd;
}
long g = Math.abs(gcd(nn, dd));
if (g > 1) {
nn /= g;
dd /= g;
}
num = nn;
denom = dd;
}
public Frac plus(Frac rhs) {
return new Frac(num * rhs.denom + denom * rhs.num, rhs.denom * denom);
}
public Frac unaryMinus() {
return new Frac(-num, denom);
}
public Frac minus(Frac rhs) {
return this.plus(rhs.unaryMinus());
}
public Frac times(Frac rhs) {
return new Frac(this.num * rhs.num, this.denom * rhs.denom);
}
@Override
public int compareTo(Frac o) {
double diff = toDouble() - o.toDouble();
return Double.compare(diff, 0.0);
}
@Override
public boolean equals(Object obj) {
return null != obj && obj instanceof Frac && this.compareTo((Frac) obj) == 0;
}
@Override
public String toString() {
if (denom == 1) {
return Long.toString(num);
}
return String.format("%d/%d", num, denom);
}
public double toDouble() {
return (double) num / denom;
}
public BigDecimal toBigDecimal() {
return BigDecimal.valueOf(num).divide(BigDecimal.valueOf(denom), MC);
}
}
private static Frac bernoulli(int n) {
if (n < 0) throw new IllegalArgumentException("n may not be negative or zero");
Frac[] a = new Frac[n + 1];
Arrays.fill(a, Frac.ZERO);
for (int m = 0; m <= n; ++m) {
a[m] = new Frac(1, m + 1);
for (int j = m; j >= 1; --j) {
a[j - 1] = a[j - 1].minus(a[j]).times(new Frac(j, 1));
}
}
// returns 'first' Bernoulli number
if (n != 1) return a[0];
return a[0].unaryMinus();
}
private static long binomial(int n, int k) {
if (n < 0 || k < 0 || n < k) throw new IllegalArgumentException();
if (n == 0 || k == 0) return 1;
long num = LongStream.rangeClosed(k + 1, n).reduce(1, (a, b) -> a * b);
long den = LongStream.rangeClosed(2, n - k).reduce(1, (acc, i) -> acc * i);
return num / den;
}
private static Frac[] faulhaberTriangle(int p) {
Frac[] coeffs = new Frac[p + 1];
Arrays.fill(coeffs, Frac.ZERO);
Frac q = new Frac(1, p + 1);
int sign = -1;
for (int j = 0; j <= p; ++j) {
sign *= -1;
coeffs[p - j] = q.times(new Frac(sign, 1)).times(new Frac(binomial(p + 1, j), 1)).times(bernoulli(j));
}
return coeffs;
}
public static void main(String[] args) {
for (int i = 0; i <= 9; ++i) {
Frac[] coeffs = faulhaberTriangle(i);
for (Frac coeff : coeffs) {
System.out.printf("%5s ", coeff);
}
System.out.println();
}
System.out.println();
// get coeffs for (k + 1)th row
int k = 17;
Frac[] cc = faulhaberTriangle(k);
int n = 1000;
BigDecimal nn = BigDecimal.valueOf(n);
BigDecimal np = BigDecimal.ONE;
BigDecimal sum = BigDecimal.ZERO;
for (Frac c : cc) {
np = np.multiply(nn);
sum = sum.add(np.multiply(c.toBigDecimal()));
}
System.out.println(sum.toBigInteger());
}
}

View file

@ -0,0 +1,279 @@
(() => {
// Order of Faulhaber's triangle -> rows of Faulhaber's triangle
// faulHaberTriangle :: Int -> [[Ratio Int]]
const faulhaberTriangle = n =>
map(x => tail(
scanl((a, x) => {
const ys = map((nd, i) =>
ratioMult(nd, Ratio(x, i + 2)), a);
return cons(ratioMinus(Ratio(1, 1), ratioSum(ys)), ys);
}, [], enumFromTo(0, x))
),
enumFromTo(0, n));
// p -> n -> Sum of the p-th powers of the first n positive integers
// faulhaber :: Int -> Ratio Int -> Ratio Int
const faulhaber = (p, n) =>
ratioSum(map(
(nd, i) => ratioMult(nd, Ratio(raise(n, i + 1), 1)),
last(faulhaberTriangle(p))
));
// RATIOS -----------------------------------------------------------------
// (Max numr + denr widths) -> Column width -> Filler -> Ratio -> String
// justifyRatio :: (Int, Int) -> Int -> Char -> Ratio Integer -> String
const justifyRatio = (ws, n, c, nd) => {
const
w = max(n, ws.nMax + ws.dMax + 2),
[num, den] = [nd.num, nd.den];
return all(Number.isSafeInteger, [num, den]) ? (
den === 1 ? center(w, c, show(num)) : (() => {
const [q, r] = quotRem(w - 1, 2);
return concat([
justifyRight(q, c, show(num)),
'/',
justifyLeft(q + r, c, (show(den)))
]);
})()
) : "JS integer overflow ... ";
};
// Ratio :: Int -> Int -> Ratio
const Ratio = (n, d) => ({
num: n,
den: d
});
// ratioMinus :: Ratio -> Ratio -> Ratio
const ratioMinus = (nd, nd1) => {
const
d = lcm(nd.den, nd1.den);
return simpleRatio({
num: (nd.num * (d / nd.den)) - (nd1.num * (d / nd1.den)),
den: d
});
};
// ratioMult :: Ratio -> Ratio -> Ratio
const ratioMult = (nd, nd1) => simpleRatio({
num: nd.num * nd1.num,
den: nd.den * nd1.den
});
// ratioPlus :: Ratio -> Ratio -> Ratio
const ratioPlus = (nd, nd1) => {
const
d = lcm(nd.den, nd1.den);
return simpleRatio({
num: (nd.num * (d / nd.den)) + (nd1.num * (d / nd1.den)),
den: d
});
};
// ratioSum :: [Ratio] -> Ratio
const ratioSum = xs =>
simpleRatio(foldl((a, x) => ratioPlus(a, x), {
num: 0,
den: 1
}, xs));
// ratioWidths :: [[Ratio]] -> {nMax::Int, dMax::Int}
const ratioWidths = xss => {
return foldl((a, x) => {
const [nw, dw] = ap(
[compose(length, show)], [x.num, x.den]
), [an, ad] = ap(
[curry(flip(lookup))(a)], ['nMax', 'dMax']
);
return {
nMax: nw > an ? nw : an,
dMax: dw > ad ? dw : ad
};
}, {
nMax: 0,
dMax: 0
}, concat(xss));
};
// simpleRatio :: Ratio -> Ratio
const simpleRatio = nd => {
const g = gcd(nd.num, nd.den);
return {
num: nd.num / g,
den: nd.den / g
};
};
// GENERIC FUNCTIONS ------------------------------------------------------
// all :: (a -> Bool) -> [a] -> Bool
const all = (f, xs) => xs.every(f);
// A list of functions applied to a list of arguments
// <*> :: [(a -> b)] -> [a] -> [b]
const ap = (fs, xs) => //
[].concat.apply([], fs.map(f => //
[].concat.apply([], xs.map(x => [f(x)]))));
// Size of space -> filler Char -> Text -> Centered Text
// center :: Int -> Char -> Text -> Text
const center = (n, c, s) => {
const [q, r] = quotRem(n - s.length, 2);
return concat(concat([replicate(q, c), s, replicate(q + r, c)]));
};
// compose :: (b -> c) -> (a -> b) -> (a -> c)
const compose = (f, g) => x => f(g(x));
// concat :: [[a]] -> [a] | [String] -> String
const concat = xs =>
xs.length > 0 ? (() => {
const unit = typeof xs[0] === 'string' ? '' : [];
return unit.concat.apply(unit, xs);
})() : [];
// cons :: a -> [a] -> [a]
const cons = (x, xs) => [x].concat(xs);
// 2 or more arguments
// curry :: Function -> Function
const curry = (f, ...args) => {
const go = xs => xs.length >= f.length ? (f.apply(null, xs)) :
function () {
return go(xs.concat(Array.from(arguments)));
};
return go([].slice.call(args, 1));
};
// enumFromTo :: Int -> Int -> [Int]
const enumFromTo = (m, n) =>
Array.from({
length: Math.floor(n - m) + 1
}, (_, i) => m + i);
// flip :: (a -> b -> c) -> b -> a -> c
const flip = f => (a, b) => f.apply(null, [b, a]);
// foldl :: (b -> a -> b) -> b -> [a] -> b
const foldl = (f, a, xs) => xs.reduce(f, a);
// gcd :: Integral a => a -> a -> a
const gcd = (x, y) => {
const _gcd = (a, b) => (b === 0 ? a : _gcd(b, a % b)),
abs = Math.abs;
return _gcd(abs(x), abs(y));
};
// head :: [a] -> a
const head = xs => xs.length ? xs[0] : undefined;
// intercalate :: String -> [a] -> String
const intercalate = (s, xs) => xs.join(s);
// justifyLeft :: Int -> Char -> Text -> Text
const justifyLeft = (n, cFiller, strText) =>
n > strText.length ? (
(strText + cFiller.repeat(n))
.substr(0, n)
) : strText;
// justifyRight :: Int -> Char -> Text -> Text
const justifyRight = (n, cFiller, strText) =>
n > strText.length ? (
(cFiller.repeat(n) + strText)
.slice(-n)
) : strText;
// last :: [a] -> a
const last = xs => xs.length ? xs.slice(-1)[0] : undefined;
// length :: [a] -> Int
const length = xs => xs.length;
// lcm :: Integral a => a -> a -> a
const lcm = (x, y) =>
(x === 0 || y === 0) ? 0 : Math.abs(Math.floor(x / gcd(x, y)) * y);
// lookup :: Eq a => a -> [(a, b)] -> Maybe b
const lookup = (k, pairs) => {
if (Array.isArray(pairs)) {
let m = pairs.find(x => x[0] === k);
return m ? m[1] : undefined;
} else {
return typeof pairs === 'object' ? (
pairs[k]
) : undefined;
}
};
// map :: (a -> b) -> [a] -> [b]
const map = (f, xs) => xs.map(f);
// max :: Ord a => a -> a -> a
const max = (a, b) => b > a ? b : a;
// min :: Ord a => a -> a -> a
const min = (a, b) => b < a ? b : a;
// quotRem :: Integral a => a -> a -> (a, a)
const quotRem = (m, n) => [Math.floor(m / n), m % n];
// raise :: Num -> Int -> Num
const raise = (n, e) => Math.pow(n, e);
// replicate :: Int -> a -> [a]
const replicate = (n, x) =>
Array.from({
length: n
}, () => x);
// scanl :: (b -> a -> b) -> b -> [a] -> [b]
const scanl = (f, startValue, xs) =>
xs.reduce((a, x) => {
const v = f(a.acc, x);
return {
acc: v,
scan: cons(a.scan, v)
};
}, {
acc: startValue,
scan: [startValue]
})
.scan;
// show :: a -> String
const show = (...x) =>
JSON.stringify.apply(
null, x.length > 1 ? [x[0], null, x[1]] : x
);
// tail :: [a] -> [a]
const tail = xs => xs.length ? xs.slice(1) : undefined;
// unlines :: [String] -> String
const unlines = xs => xs.join('\n');
// TEST -------------------------------------------------------------------
const
triangle = faulhaberTriangle(9),
widths = ratioWidths(triangle);
return unlines(
map(row =>
concat(map(cell =>
justifyRatio(widths, 8, ' ', cell), row)), triangle)
) +
'\n\n' + unlines(
[
'faulhaber(17, 1000)',
justifyRatio(widths, 0, ' ', faulhaber(17, 1000)),
'\nfaulhaber(17, 8)',
justifyRatio(widths, 0, ' ', faulhaber(17, 8)),
'\nfaulhaber(4, 1000)',
justifyRatio(widths, 0, ' ', faulhaber(4, 1000)),
]
);
})();

View file

@ -0,0 +1,68 @@
include "Rational";
# Preliminaries
def lpad($len): tostring | ($len - length) as $l | (" " * $l)[:$l] + .;
# for gojq
def idivide($j):
. as $i
| ($i % $j) as $mod
| ($i - $mod) / $j ;
# use idivide for precision
def binomial(n; k):
if k > n / 2 then binomial(n; n-k)
else reduce range(1; k+1) as $i (1; . * (n - $i + 1) | idivide($i))
end;
# Here we conform to the modern view that B(1) is 1 // 2
def bernoulli:
if type != "number" or . < 0 then "bernoulli must be given a non-negative number vs \(.)" | error
else . as $n
| reduce range(0; $n+1) as $i ([];
.[$i] = r(1; $i + 1)
| reduce range($i; 0; -1) as $j (.;
.[$j-1] = rmult($j; rminus(.[$j-1]; .[$j])) ) )
| .[0] # the modern view
end;
# Input: a non-negative integer, $p
# Output: an array of Rationals corresponding to the
# Faulhaber coefficients for row ($p + 1) (counting the first row as row 1).
def faulhabercoeffs:
def altBernoulli: # adjust B(1) for this task
bernoulli as $b
| if . == 1 then rmult(-1; $b) else $b end;
. as $p
| r(1; $p + 1) as $q
| { coeffs: [], sign: -1 }
| reduce range(0; $p+1) as $j (.;
.sign *= -1
| binomial($p + 1; $j) as $b
| .coeffs[$p - $j] = ([ .sign, $q, $b, ($j|altBernoulli) ] | rmult))
| .coeffs
;
# Calculate the sum for ($k|faulhabercoeffs)
def faulhabersum($n; $k):
($k|faulhabercoeffs) as $coe
| reduce range(0;$k+1) as $i ({sum: 0, power: 1};
.power *= $n
| .sum = radd(.sum; rmult(.power; $coe[$i]))
)
| .sum;
# pretty print a Rational assumed to have the {n,d} form
def rpp:
if .n == 0 then "0"
elif .d == 1 then .n | tostring
else "\(.n)/\(.d)"
end;
def testfaulhaber:
(range(0; 10) as $i
| ($i | faulhabercoeffs | map(rpp | lpad(6)) | join(" "))),
"\nfaulhabersum(1000; 17):",
(faulhabersum(1000; 17) | rpp) ;
testfaulhaber

View file

@ -0,0 +1,37 @@
function bernoulli(n)
A = Vector{Rational{BigInt}}(undef, n + 1)
for i in 0:n
A[i + 1] = 1 // (i + 1)
for j = i:-1:1
A[j] = j * (A[j] - A[j + 1])
end
end
return n == 1 ? -A[1] : A[1]
end
function faulhabercoeffs(p)
coeffs = Vector{Rational{BigInt}}(undef, p + 1)
q = Rational{BigInt}(1, p + 1)
sign = -1
for j in 0:p
sign *= -1
coeffs[p - j + 1] = bernoulli(j) * (q * sign) * Rational{BigInt}(binomial(p + 1, j), 1)
end
coeffs
end
faulhabersum(n, k) = begin coe = faulhabercoeffs(k); mapreduce(i -> BigInt(n)^i * coe[i], +, 1:k+1) end
prettyfrac(x) = (x.num == 0 ? "0" : x.den == 1 ? string(x.num) : replace(string(x), "//" => "/"))
function testfaulhaber()
for i in 0:9
for c in faulhabercoeffs(i)
print(prettyfrac(c), "\t")
end
println()
end
println("\n", prettyfrac(faulhabersum(1000, 17)))
end
testfaulhaber()

View file

@ -0,0 +1,121 @@
// version 1.1.2
import java.math.BigDecimal
import java.math.MathContext
val mc = MathContext(256)
fun gcd(a: Long, b: Long): Long = if (b == 0L) a else gcd(b, a % b)
class Frac : Comparable<Frac> {
val num: Long
val denom: Long
companion object {
val ZERO = Frac(0, 1)
val ONE = Frac(1, 1)
}
constructor(n: Long, d: Long) {
require(d != 0L)
var nn = n
var dd = d
if (nn == 0L) {
dd = 1
}
else if (dd < 0) {
nn = -nn
dd = -dd
}
val g = Math.abs(gcd(nn, dd))
if (g > 1) {
nn /= g
dd /= g
}
num = nn
denom = dd
}
constructor(n: Int, d: Int) : this(n.toLong(), d.toLong())
operator fun plus(other: Frac) =
Frac(num * other.denom + denom * other.num, other.denom * denom)
operator fun unaryMinus() = Frac(-num, denom)
operator fun minus(other: Frac) = this + (-other)
operator fun times(other: Frac) = Frac(this.num * other.num, this.denom * other.denom)
fun abs() = if (num >= 0) this else -this
override fun compareTo(other: Frac): Int {
val diff = this.toDouble() - other.toDouble()
return when {
diff < 0.0 -> -1
diff > 0.0 -> +1
else -> 0
}
}
override fun equals(other: Any?): Boolean {
if (other == null || other !is Frac) return false
return this.compareTo(other) == 0
}
override fun toString() = if (denom == 1L) "$num" else "$num/$denom"
fun toDouble() = num.toDouble() / denom
fun toBigDecimal() = BigDecimal(num).divide(BigDecimal(denom), mc)
}
fun bernoulli(n: Int): Frac {
require(n >= 0)
val a = Array(n + 1) { Frac.ZERO }
for (m in 0..n) {
a[m] = Frac(1, m + 1)
for (j in m downTo 1) a[j - 1] = (a[j - 1] - a[j]) * Frac(j, 1)
}
return if (n != 1) a[0] else -a[0] // returns 'first' Bernoulli number
}
fun binomial(n: Int, k: Int): Long {
require(n >= 0 && k >= 0 && n >= k)
if (n == 0 || k == 0) return 1
val num = (k + 1..n).fold(1L) { acc, i -> acc * i }
val den = (2..n - k).fold(1L) { acc, i -> acc * i }
return num / den
}
fun faulhaberTriangle(p: Int): Array<Frac> {
val coeffs = Array(p + 1) { Frac.ZERO }
val q = Frac(1, p + 1)
var sign = -1
for (j in 0..p) {
sign *= -1
coeffs[p - j] = q * Frac(sign, 1) * Frac(binomial(p + 1, j), 1) * bernoulli(j)
}
return coeffs
}
fun main(args: Array<String>) {
for (i in 0..9){
val coeffs = faulhaberTriangle(i)
for (coeff in coeffs) print("${coeff.toString().padStart(5)} ")
println()
}
println()
// get coeffs for (k + 1)th row
val k = 17
val cc = faulhaberTriangle(k)
val n = 1000
val nn = BigDecimal(n)
var np = BigDecimal.ONE
var sum = BigDecimal.ZERO
for (c in cc) {
np *= nn
sum += np * c.toBigDecimal()
}
println(sum.toBigInteger())
}

View file

@ -0,0 +1,123 @@
function binomial(n,k)
if n<0 or k<0 or n<k then return -1 end
if n==0 or k==0 then return 1 end
local num = 1
for i=k+1,n do
num = num * i
end
local denom = 1
for i=2,n-k do
denom = denom * i
end
return num / denom
end
function gcd(a,b)
while b ~= 0 do
local temp = a % b
a = b
b = temp
end
return a
end
function makeFrac(n,d)
local result = {}
if d==0 then
result.num = 0
result.denom = 0
return result
end
if n==0 then
d = 1
elseif d < 0 then
n = -n
d = -d
end
local g = math.abs(gcd(n, d))
if g>1 then
n = n / g
d = d / g
end
result.num = n
result.denom = d
return result
end
function negateFrac(f)
return makeFrac(-f.num, f.denom)
end
function subFrac(lhs, rhs)
return makeFrac(lhs.num * rhs.denom - lhs.denom * rhs.num, rhs.denom * lhs.denom)
end
function multFrac(lhs, rhs)
return makeFrac(lhs.num * rhs.num, lhs.denom * rhs.denom)
end
function equalFrac(lhs, rhs)
return (lhs.num == rhs.num) and (lhs.denom == rhs.denom)
end
function lessFrac(lhs, rhs)
return (lhs.num * rhs.denom) < (rhs.num * lhs.denom)
end
function printFrac(f)
local str = tostring(f.num)
if f.denom ~= 1 then
str = str.."/"..f.denom
end
for i=1, 7 - string.len(str) do
io.write(" ")
end
io.write(str)
return nil
end
function bernoulli(n)
if n<0 then
return {num=0, denom=0}
end
local a = {}
for m=0,n do
a[m] = makeFrac(1, m+1)
for j=m,1,-1 do
a[j-1] = multFrac(subFrac(a[j-1], a[j]), makeFrac(j, 1))
end
end
if n~=1 then
return a[0]
end
return negateFrac(a[0])
end
function faulhaber(p)
local q = makeFrac(1, p+1)
local sign = -1
local coeffs = {}
for j=0,p do
sign = -1 * sign
coeffs[p-j] = multFrac(multFrac(multFrac(q, makeFrac(sign, 1)), makeFrac(binomial(p + 1, j), 1)), bernoulli(j))
end
for j=0,p do
printFrac(coeffs[j])
end
print()
return nil
end
-- main
for i=0,9 do
faulhaber(i)
end

View file

@ -0,0 +1,6 @@
ClearAll[Faulhaber]
bernoulliB[1] := 1/2
bernoulliB[n_] := BernoulliB[n]
Faulhaber[n_, p_] := 1/(p + 1) Sum[Binomial[p + 1, j] bernoulliB[j] n^(p + 1 - j), {j, 0, p}]
Table[Rest@CoefficientList[Faulhaber[n, t], n], {t, 0, 9}] // Grid
Faulhaber[1000, 17]

View file

@ -0,0 +1,57 @@
import algorithm, math, strutils
import bignum
type FaulhaberSequence = seq[Rat]
#---------------------------------------------------------------------------------------------------
func bernoulli(n: Natural): Rat =
## Return nth Bernoulli coefficient.
var a = newSeq[Rat](n + 1)
for m in 0..n:
a[m] = newRat(1, m + 1)
for k in countdown(m, 1):
a[k - 1] = (a[k - 1] - a[k]) * k
result = if n != 1: a[0] else: -a[0]
#---------------------------------------------------------------------------------------------------
func faulhaber(n: Natural): FaulhaberSequence =
## Return nth Faulhaber sequence (high degree first).
var a = newRat(1, n + 1)
var sign = -1
for k in 0..n:
sign = -sign
result.add(a * sign * binom(n + 1, k) * bernoulli(k))
#---------------------------------------------------------------------------------------------------
proc display(fs: FaulhaberSequence) =
## Return the string representing a Faulhaber sequence.
var str = ""
for i, coeff in reversed(fs):
str.addSep(" ", 0)
str.add(($coeff).align(6))
echo str
#---------------------------------------------------------------------------------------------------
func evaluate(fs: FaulhaberSequence; n: int): Rat =
## Evaluate the polynomial associated to a sequence for value "n".
result = newRat(0)
for coeff in fs:
result = result * n + coeff
result *= n
#———————————————————————————————————————————————————————————————————————————————————————————————————
for n in 0..9:
display(faulhaber(n))
echo ""
let fs18 = faulhaber(17) # 18th row.
echo fs18.evaluate(1000)

View file

@ -0,0 +1,64 @@
program FaulhaberTriangle;
uses uIntX, uEnums, // units in the library IntXLib4Pascal
SysUtils;
// Convert a rational num/den to a string, right-justified in the given width.
// Before converting, remove any common factor of num and den.
// For this application we can assume den > 0.
function RationalToString( num, den : TIntX;
minWidth : integer) : string;
var
num1, den1, divisor : TIntX;
w : integer;
begin
divisor := TIntX.GCD( num, den);
// TIntx.Divide requires the caller to specifiy the division mode
num1 := TIntx.Divide( num, divisor, uEnums.dmClassic);
den1 := TIntx.Divide( den, divisor, uEnums.dmClassic);
result := num1.ToString;
if not den1.IsOne then result := result + '/' + den1.ToString;
w := minWidth - Length( result);
if (w > 0) then result := StringOfChar(' ', w) + result;
end;
// Main routine
const
r_MAX = 17;
var
g : array [1..r_MAX + 1] of TIntX;
r, s, k : integer;
r_1_fac, sum, k_intx : TIntX;
begin
// Calculate rows 0..17 of Faulhaner's triangle, and show rows 0..9.
// For a given r, the subarray g[1..(r+1)] contains (r + 1)! times row r.
r_1_fac := 1; // (r + 1)!
g[1] := 1;
for r := 0 to r_MAX do begin
r_1_fac := r_1_fac * (r+1);
sum := 0;
for s := r downto 1 do begin
g[s + 1] := r*(r+1)*g[s] div (s+1);
sum := sum + g[s + 1];
end;
g[1] := r_1_fac - sum; // the scaled row must sum to (r + 1)!
if (r <= 9) then begin
for s := 1 to r + 1 do Write( RationalToString( g[s], r_1_fac, 7));
WriteLn;
end;
end;
// Use row 17 to sum 17th powers from 1 to 1000
sum := 0;
for s := r_MAX + 1 downto 1 do sum := (sum + g[s]) * 1000;
sum := TIntx.Divide( sum, r_1_fac, uEnums.dmClassic);
WriteLn;
WriteLn( 'Sum by Faulhaber = ' + sum.ToString);
// Check by direct calculation
sum := 0;
for k := 1 to 1000 do begin
k_intx := k;
sum := sum + TIntX.Pow( k_intx, r_MAX);
end;
WriteLn( 'by direct calc. = ' + sum.ToString);
end.

View file

@ -0,0 +1,24 @@
use 5.010;
use List::Util qw(sum);
use Math::BigRat try => 'GMP';
use ntheory qw(binomial bernfrac);
sub faulhaber_triangle {
my ($p) = @_;
map {
Math::BigRat->new(bernfrac($_))
* binomial($p, $_)
/ $p
} reverse(0 .. $p-1);
}
# First 10 rows of Faulhaber's triangle
foreach my $p (1 .. 10) {
say map { sprintf("%6s", $_) } faulhaber_triangle($p);
}
# Extra credit
my $p = 17;
my $n = Math::BigInt->new(1000);
my @r = faulhaber_triangle($p+1);
say "\n", sum(map { $r[$_] * $n**($_ + 1) } 0 .. $#r);

View file

@ -0,0 +1,60 @@
(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #008080;">include</span> <span style="color: #000000;">builtins</span><span style="color: #0000FF;">\</span><span style="color: #000000;">pfrac</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span> <span style="color: #000080;font-style:italic;">-- (0.8.0+)</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">bernoulli</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">a</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">m</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">to</span> <span style="color: #000000;">n</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">a</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">append</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">m</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">m</span> <span style="color: #008080;">to</span> <span style="color: #000000;">1</span> <span style="color: #008080;">by</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">a</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">frac_mul</span><span style="color: #0000FF;">({</span><span style="color: #000000;">j</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">},</span><span style="color: #000000;">frac_sub</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">],</span><span style="color: #000000;">a</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]))</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">frac_uminus</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">])</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">binomial</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">k</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">n</span><span style="color: #0000FF;"><</span><span style="color: #000000;">0</span> <span style="color: #008080;">or</span> <span style="color: #000000;">k</span><span style="color: #0000FF;"><</span><span style="color: #000000;">0</span> <span style="color: #008080;">or</span> <span style="color: #000000;">n</span><span style="color: #0000FF;"><</span><span style="color: #000000;">k</span> <span style="color: #008080;">then</span> <span style="color: #0000FF;">?</span><span style="color: #000000;">9</span><span style="color: #0000FF;">/</span><span style="color: #000000;">0</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">or</span> <span style="color: #000000;">k</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #000000;">1</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">num</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">denom</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">k</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">n</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">num</span> <span style="color: #0000FF;">*=</span> <span style="color: #000000;">i</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">2</span> <span style="color: #008080;">to</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">-</span><span style="color: #000000;">k</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">denom</span> <span style="color: #0000FF;">*=</span> <span style="color: #000000;">i</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">num</span> <span style="color: #0000FF;">/</span> <span style="color: #000000;">denom</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">faulhaber_triangle</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">p</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">bool</span> <span style="color: #000000;">asString</span><span style="color: #0000FF;">=</span><span style="color: #004600;">true</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">coeffs</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">frac_zero</span><span style="color: #0000FF;">,</span><span style="color: #000000;">p</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">to</span> <span style="color: #000000;">p</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">frac</span> <span style="color: #000000;">coeff</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">frac_mul</span><span style="color: #0000FF;">({</span><span style="color: #000000;">binomial</span><span style="color: #0000FF;">(</span><span style="color: #000000;">p</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">j</span><span style="color: #0000FF;">),</span><span style="color: #000000;">p</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">},</span><span style="color: #000000;">bernoulli</span><span style="color: #0000FF;">(</span><span style="color: #000000;">j</span><span style="color: #0000FF;">))</span>
<span style="color: #000000;">coeffs</span><span style="color: #0000FF;">[</span><span style="color: #000000;">p</span><span style="color: #0000FF;">-</span><span style="color: #000000;">j</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">asString</span><span style="color: #0000FF;">?</span><span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"%5s"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">frac_sprint</span><span style="color: #0000FF;">(</span><span style="color: #000000;">coeff</span><span style="color: #0000FF;">)}):</span><span style="color: #000000;">coeff</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">coeffs</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">to</span> <span style="color: #000000;">9</span> <span style="color: #008080;">do</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #7060A8;">join</span><span style="color: #0000FF;">(</span><span style="color: #000000;">faulhaber_triangle</span><span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;">),</span><span style="color: #008000;">" "</span><span style="color: #0000FF;">)})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\n"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">platform</span><span style="color: #0000FF;">()!=</span><span style="color: #004600;">JS</span> <span style="color: #008080;">then</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">row18</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">faulhaber_triangle</span><span style="color: #0000FF;">(</span><span style="color: #000000;">17</span><span style="color: #0000FF;">,</span><span style="color: #004600;">false</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">frac</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">frac_zero</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">t1</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">time</span><span style="color: #0000FF;">()+</span><span style="color: #000000;">1</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">lim</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1000</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">k</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">lim</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">bigatom</span> <span style="color: #000000;">nn</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">BA_ONE</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">row18</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">frac_add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">,</span><span style="color: #000000;">frac_mul</span><span style="color: #0000FF;">(</span><span style="color: #000000;">row18</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">],{</span><span style="color: #000000;">nn</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">}))</span>
<span style="color: #000000;">nn</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">ba_mul</span><span style="color: #0000FF;">(</span><span style="color: #000000;">nn</span><span style="color: #0000FF;">,</span><span style="color: #000000;">lim</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">time</span><span style="color: #0000FF;">()></span><span style="color: #000000;">t1</span> <span style="color: #008080;">then</span> <span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"calculating, k=%d...\r"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">k</span><span style="color: #0000FF;">)</span> <span style="color: #000000;">t1</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">time</span><span style="color: #0000FF;">()+</span><span style="color: #000000;">1</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%s \n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">frac_sprint</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">)})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<!--

View file

@ -0,0 +1,33 @@
ft_rows(Lz) :-
lazy_list(ft_row, [], Lz).
ft_row([], R1, R1) :- R1 = [1].
ft_row(R0, R2, R2) :-
length(R0, P),
Jmax is 1 + P, numlist(2, Jmax, Qs),
maplist(term(P), Qs, R0, R1),
sum_list(R1, S), Bk is 1 - S, % Bk is Bernoulli number
R2 = [Bk | R1].
term(P, Q, R, S) :- S is R * (P rdiv Q).
show(N) :-
ft_rows(Rs),
length(Rows, N), prefix(Rows, Rs),
forall(
member(R, Rows),
(format(string(S), "~w", [R]),
re_replace(" rdiv "/g, "/", S, T),
re_replace(","/g, ", ", T, U),
write(U), nl)).
sum(N, K, S) :- % sum I=1,N (I ** K)
ft_rows(Rows), drop(K, Rows, [Coefs|_]),
reverse([0|Coefs], Poly),
foldl(horner(N), Poly, 0, S).
horner(N, A, S0, S1) :-
S1 is N*S0 + A.
drop(N, Lz1, Lz2) :-
append(Pfx, Lz2, Lz1), length(Pfx, N), !.

View file

@ -0,0 +1,148 @@
'''Faulhaber's triangle'''
from itertools import accumulate, chain, count, islice
from fractions import Fraction
# faulhaberTriangle :: Int -> [[Fraction]]
def faulhaberTriangle(m):
'''List of rows of Faulhaber fractions.'''
def go(rs, n):
def f(x, y):
return Fraction(n, x) * y
xs = list(map(f, islice(count(2), m), rs))
return [Fraction(1 - sum(xs), 1)] + xs
return list(accumulate(
[[]] + list(islice(count(0), 1 + m)),
go
))[1:]
# faulhaberSum :: Integer -> Integer -> Integer
def faulhaberSum(p, n):
'''Sum of the p-th powers of the first n
positive integers.
'''
def go(x, y):
return y * (n ** x)
return sum(
map(go, count(1), faulhaberTriangle(p)[-1])
)
# ------------------------- TEST -------------------------
def main():
'''Tests'''
fs = faulhaberTriangle(9)
print(
fTable(__doc__ + ':\n')(str)(
compose(concat)(
fmap(showRatio(3)(3))
)
)(
index(fs)
)(range(0, len(fs)))
)
print('')
print(
faulhaberSum(17, 1000)
)
# ----------------------- DISPLAY ------------------------
# fTable :: String -> (a -> String) ->
# (b -> String) -> (a -> b) -> [a] -> String
def fTable(s):
'''Heading -> x display function ->
fx display function -> f -> xs -> tabular string.
'''
def gox(xShow):
def gofx(fxShow):
def gof(f):
def goxs(xs):
ys = [xShow(x) for x in xs]
w = max(map(len, ys))
def arrowed(x, y):
return y.rjust(w, ' ') + ' -> ' + (
fxShow(f(x))
)
return s + '\n' + '\n'.join(
map(arrowed, xs, ys)
)
return goxs
return gof
return gofx
return gox
# ----------------------- GENERIC ------------------------
# compose (<<<) :: (b -> c) -> (a -> b) -> a -> c
def compose(g):
'''Right to left function composition.'''
return lambda f: lambda x: g(f(x))
# concat :: [[a]] -> [a]
# concat :: [String] -> String
def concat(xs):
'''The concatenation of all the elements
in a list or iterable.
'''
def f(ys):
zs = list(chain(*ys))
return ''.join(zs) if isinstance(ys[0], str) else zs
return (
f(xs) if isinstance(xs, list) else (
chain.from_iterable(xs)
)
) if xs else []
# fmap :: (a -> b) -> [a] -> [b]
def fmap(f):
'''fmap over a list.
f lifted to a function over a list.
'''
def go(xs):
return list(map(f, xs))
return go
# index (!!) :: [a] -> Int -> a
def index(xs):
'''Item at given (zero-based) index.'''
return lambda n: None if 0 > n else (
xs[n] if (
hasattr(xs, "__getitem__")
) else next(islice(xs, n, None))
)
# showRatio :: Int -> Int -> Ratio -> String
def showRatio(m):
'''Left and right aligned string
representation of the ratio r.
'''
def go(n):
def f(r):
d = r.denominator
return str(r.numerator).rjust(m, ' ') + (
('/' + str(d).ljust(n, ' ')) if 1 != d else (
' ' * (1 + n)
)
)
return f
return go
# MAIN ---
if __name__ == '__main__':
main()

View file

@ -0,0 +1,99 @@
Numeric Digits 100
Do r=0 To 20
ra=r-1
If r=0 Then
f.r.1=1
Else Do
rsum=0
Do c=2 To r+1
ca=c-1
f.r.c=fdivide(fmultiply(f.ra.ca,r),c)
rsum=fsum(rsum,f.r.c)
End
f.r.1=fsubtract(1,rsum)
End
End
Do r=0 To 9
ol=''
Do c=1 To r+1
ol=ol right(f.r.c,5)
End
Say ol
End
Say ''
x=0
Do c=1 To 18
x=fsum(x,fmultiply(f.17.c,(1000**c)))
End
Say k(x)
s=0
Do k=1 To 1000
s=s+k**17
End
Say s
Exit
fmultiply: Procedure
Parse Arg a,b
Parse Var a ad '/' an
Parse Var b bd '/' bn
If an='' Then an=1
If bn='' Then bn=1
res=(abs(ad)*abs(bd))'/'||(an*bn)
Return s(ad,bd)k(res)
fdivide: Procedure
Parse Arg a,b
Parse Var a ad '/' an
Parse Var b bd '/' bn
If an='' Then an=1
If bn='' Then bn=1
res=s(ad,bd)(abs(ad)*bn)'/'||(an*abs(bd))
Return k(res)
fsum: Procedure
Parse Arg a,b
Parse Var a ad '/' an
Parse Var b bd '/' bn
If an='' Then an=1
If bn='' Then bn=1
n=an*bn
d=ad*bn+bd*an
res=d'/'n
Return k(res)
fsubtract: Procedure
Parse Arg a,b
Parse Var a ad '/' an
Parse Var b bd '/' bn
If an='' Then an=1
If bn='' Then bn=1
n=an*bn
d=ad*bn-bd*an
res=d'/'n
Return k(res)
s: Procedure
Parse Arg ad,bd
s=sign(ad)*sign(bd)
If s<0 Then Return '-'
Else Return ''
k: Procedure
Parse Arg a
Parse Var a ad '/' an
Select
When ad=0 Then Return 0
When an=1 Then Return ad
Otherwise Do
g=gcd(ad,an)
ad=ad/g
an=an/g
Return ad'/'an
End
End
gcd: procedure
Parse Arg a,b
if b = 0 then return abs(a)
return gcd(b,a//b)

View file

@ -0,0 +1,24 @@
#lang racket
(require math/number-theory)
(define (second-bernoulli-number n)
(if (= n 1) 1/2 (bernoulli-number n)))
(define (faulhaber-row:formulaic p)
(let ((p+1 (+ p 1)))
(reverse
(for/list ((j (in-range p+1)))
(* (/ p+1) (second-bernoulli-number j) (binomial p+1 j))))))
(define (sum-k^p:formulaic p n)
(for/sum ((f (faulhaber-row:formulaic p)) (i (in-naturals 1)))
(* f (expt n i))))
(module+ main
(map faulhaber-row:formulaic (range 10))
(sum-k^p:formulaic 17 1000))
(module+ test
(require rackunit)
(check-equal? (sum-k^p:formulaic 17 1000)
(for/sum ((k (in-range 1 (add1 1000)))) (expt k 17))))

View file

@ -0,0 +1,26 @@
# Helper subs
sub infix:<reduce> (\prev, \this) { this.key => this.key * (this.value - prev.value) }
sub next-bernoulli ( (:key($pm), :value(@pa)) ) {
$pm + 1 => [ map *.value, [\reduce] ($pm + 2 ... 1) Z=> 1 / ($pm + 2), |@pa ]
}
constant bernoulli = (0 => [1.FatRat], &next-bernoulli ... *).map: { .value[*-1] };
sub binomial (Int $n, Int $p) { combinations($n, $p).elems }
sub asRat (FatRat $r) { $r ?? $r.denominator == 1 ?? $r.numerator !! $r.nude.join('/') !! 0 }
# The task
sub faulhaber_triangle ($p) { map { binomial($p + 1, $_) * bernoulli[$_] / ($p + 1) }, ($p ... 0) }
# First 10 rows of Faulhaber's triangle:
say faulhaber_triangle($_)».&asRat.fmt('%5s') for ^10;
say '';
# Extra credit:
my $p = 17;
my $n = 1000;
say sum faulhaber_triangle($p).kv.map: { $^value * $n**($^key + 1) }

View file

@ -0,0 +1,127 @@
class Frac
attr_accessor:num
attr_accessor:denom
def initialize(n,d)
if d == 0 then
raise ArgumentError.new('d cannot be zero')
end
nn = n
dd = d
if nn == 0 then
dd = 1
elsif dd < 0 then
nn = -nn
dd = -dd
end
g = nn.abs.gcd(dd.abs)
if g > 1 then
nn = nn / g
dd = dd / g
end
@num = nn
@denom = dd
end
def to_s
if self.denom == 1 then
return self.num.to_s
else
return "%d/%d" % [self.num, self.denom]
end
end
def -@
return Frac.new(-self.num, self.denom)
end
def +(rhs)
return Frac.new(self.num * rhs.denom + self.denom * rhs.num, rhs.denom * self.denom)
end
def -(rhs)
return Frac.new(self.num * rhs.denom - self.denom * rhs.num, rhs.denom * self.denom)
end
def *(rhs)
return Frac.new(self.num * rhs.num, rhs.denom * self.denom)
end
end
FRAC_ZERO = Frac.new(0, 1)
FRAC_ONE = Frac.new(1, 1)
def bernoulli(n)
if n < 0 then
raise ArgumentError.new('n cannot be negative')
end
a = Array.new(n + 1)
a[0] = FRAC_ZERO
for m in 0 .. n do
a[m] = Frac.new(1, m + 1)
m.downto(1) do |j|
a[j - 1] = (a[j - 1] - a[j]) * Frac.new(j, 1)
end
end
if n != 1 then
return a[0]
end
return -a[0]
end
def binomial(n, k)
if n < 0 then
raise ArgumentError.new('n cannot be negative')
end
if k < 0 then
raise ArgumentError.new('k cannot be negative')
end
if n < k then
raise ArgumentError.new('n cannot be less than k')
end
if n == 0 or k == 0 then
return 1
end
num = 1
for i in k + 1 .. n do
num = num * i
end
den = 1
for i in 2 .. n - k do
den = den * i
end
return num / den
end
def faulhaberTriangle(p)
coeffs = Array.new(p + 1)
coeffs[0] = FRAC_ZERO
q = Frac.new(1, p + 1)
sign = -1
for j in 0 .. p do
sign = -sign
coeffs[p - j] = q * Frac.new(sign, 1) * Frac.new(binomial(p + 1, j), 1) * bernoulli(j)
end
return coeffs
end
def main
for i in 0 .. 9 do
coeffs = faulhaberTriangle(i)
coeffs.each do |coeff|
print "%5s " % [coeff]
end
puts
end
end
main()

View file

@ -0,0 +1,152 @@
import java.math.MathContext
import scala.collection.mutable
abstract class Frac extends Comparable[Frac] {
val num: BigInt
val denom: BigInt
def unary_-(): Frac = {
Frac(-num, denom)
}
def +(rhs: Frac): Frac = {
Frac(
num * rhs.denom + rhs.num * denom,
denom * rhs.denom
)
}
def -(rhs: Frac): Frac = {
Frac(
num * rhs.denom - rhs.num * denom,
denom * rhs.denom
)
}
def *(rhs: Frac): Frac = {
Frac(num * rhs.num, denom * rhs.denom)
}
override def compareTo(rhs: Frac): Int = {
val ln = num * rhs.denom
val rn = rhs.num * denom
ln.compare(rn)
}
def canEqual(other: Any): Boolean = other.isInstanceOf[Frac]
override def equals(other: Any): Boolean = other match {
case that: Frac =>
(that canEqual this) &&
num == that.num &&
denom == that.denom
case _ => false
}
override def hashCode(): Int = {
val state = Seq(num, denom)
state.map(_.hashCode()).foldLeft(0)((a, b) => 31 * a + b)
}
override def toString: String = {
if (denom == 1) {
return s"$num"
}
s"$num/$denom"
}
}
object Frac {
val ZERO: Frac = Frac(0)
val ONE: Frac = Frac(1)
def apply(n: BigInt): Frac = new Frac {
val num: BigInt = n
val denom: BigInt = 1
}
def apply(n: BigInt, d: BigInt): Frac = {
if (d == 0) {
throw new IllegalArgumentException("Parameter d may not be zero.")
}
var nn = n
var dd = d
if (nn == 0) {
dd = 1
} else if (dd < 0) {
nn = -nn
dd = -dd
}
val g = nn.gcd(dd)
if (g > 0) {
nn /= g
dd /= g
}
new Frac {
val num: BigInt = nn
val denom: BigInt = dd
}
}
}
object Faulhaber {
def bernoulli(n: Int): Frac = {
if (n < 0) {
throw new IllegalArgumentException("n may not be negative or zero")
}
val a = Array.fill(n + 1)(Frac.ZERO)
for (m <- 0 to n) {
a(m) = Frac(1, m + 1)
for (j <- m to 1 by -1) {
a(j - 1) = (a(j - 1) - a(j)) * Frac(j)
}
}
// returns 'first' Bernoulli number
if (n != 1) {
return a(0)
}
-a(0)
}
def binomial(n: Int, k: Int): Int = {
if (n < 0 || k < 0 || n < k) {
throw new IllegalArgumentException()
}
if (n == 0 || k == 0) {
return 1
}
val num = (k + 1 to n).product
val den = (2 to n - k).product
num / den
}
def faulhaberTriangle(p: Int): List[Frac] = {
val coeffs = mutable.MutableList.fill(p + 1)(Frac.ZERO)
val q = Frac(1, p + 1)
var sign = -1
for (j <- 0 to p) {
sign *= -1
coeffs(p - j) = q * Frac(sign) * Frac(binomial(p + 1, j)) * bernoulli(j)
}
coeffs.toList
}
def main(args: Array[String]): Unit = {
for (i <- 0 to 9) {
val coeffs = faulhaberTriangle(i)
for (coeff <- coeffs) {
print("%5s ".format(coeff))
}
println()
}
println()
}
}

View file

@ -0,0 +1,55 @@
; Return the first row-count rows of Faulhaber's Triangle as a vector of vectors.
(define faulhabers-triangle
(lambda (row-count)
; Calculate and store the value of the first column of a row.
; The value is one minus the sum of all the rest of the columns.
(define calc-store-first!
(lambda (row)
(vector-set! row 0
(do ((col-inx 1 (1+ col-inx))
(col-sum 0 (+ col-sum (vector-ref row col-inx))))
((>= col-inx (vector-length row)) (- 1 col-sum))))))
; Generate the Faulhaber's Triangle one row at a time.
; The element at row i >= 0, column j >= 1 (both 0-based) is the product
; of the element at i - 1, j - 1 and the fraction ( i / ( j + 1 ) ).
; The element at column 0 is one minus the sum of all the rest of the columns.
(let ((tri (make-vector row-count)))
(do ((row-inx 0 (1+ row-inx)))
((>= row-inx row-count) tri)
(let ((row (make-vector (1+ row-inx))))
(vector-set! tri row-inx row)
(do ((col-inx 1 (1+ col-inx)))
((>= col-inx (vector-length row)))
(vector-set! row col-inx
(* (vector-ref (vector-ref tri (1- row-inx)) (1- col-inx))
(/ row-inx (1+ col-inx)))))
(calc-store-first! row))))))
; Convert elements of a vector to a string for display.
(define vector->string
(lambda (vec)
(do ((inx 0 (1+ inx))
(str "" (string-append str (format "~7@a" (vector-ref vec inx)))))
((>= inx (vector-length vec)) str))))
; Display a Faulhaber's Triangle.
(define faulhabers-triangle-display
(lambda (tri)
(do ((inx 0 (1+ inx)))
((>= inx (vector-length tri)))
(printf "~a~%" (vector->string (vector-ref tri inx))))))
; Task..
(let ((row-count 10))
(printf "The first ~a rows of Faulhaber's Triangle..~%" row-count)
(faulhabers-triangle-display (faulhabers-triangle row-count)))
(newline)
(let ((power 17)
(sum-to 1000))
(printf "Sum over k=1..~a of k^~a using Faulhaber's Triangle..~%" sum-to power)
(let* ((tri (faulhabers-triangle (1+ power)))
(coefs (vector-ref tri power)))
(printf "~a~%" (do ((inx 0 (1+ inx))
(term-expt sum-to (* term-expt sum-to))
(sum 0 (+ sum (* (vector-ref coefs inx) term-expt))))
((>= inx (vector-length coefs)) sum)))))

View file

@ -0,0 +1,13 @@
func faulhaber_triangle(p) {
{ binomial(p, _) * bernoulli(_) / p }.map(p ^.. 0)
}
{ |p|
say faulhaber_triangle(p).map{ '%6s' % .as_rat }.join
} << 1..10
const p = 17
const n = 1000
say ''
say faulhaber_triangle(p+1).map_kv {|k,v| v * n**(k+1) }.sum

View file

@ -0,0 +1,22 @@
func find_poly_degree(a) {
var c = 0
loop {
++c
a = a.map_cons(2, {|n,k| n-k })
return 0 if a.is_empty
return c if a.all { .is_zero }
}
}
func faulhaber_triangle(n) {
var a = (0..(n+2) -> accumulate { _**n })
var c = find_poly_degree(a)
var A = c.of {|n|
c.of {|k| n**k }
}
A.msolve(a).slice(1)
}
10.times { say faulhaber_triangle(_) }

View file

@ -0,0 +1,64 @@
import math.fractions
import math.big
fn bernoulli(n int) fractions.Fraction {
mut a := []fractions.Fraction{len: n+1}
for m,_ in a {
a[m] = fractions.fraction(1, i64(m+1))
for j := m; j >= 1; j-- {
mut d := a[j-1]
d = fractions.fraction(i64(j),i64(1)) * (d-a[j])
a[j-1]=d
}
}
// return the 'first' Bernoulli number
if n != 1 {
return a[0]
}
a[0] = a[0].negate()
return a[0]
}
fn binomial(n int, k int) i64 {
if n <= 0 || k <= 0 || n < k {
return 1
}
mut num, mut den := i64(1), i64(1)
for i := k + 1; i <= n; i++ {
num *= i64(i)
}
for i := 2; i <= n-k; i++ {
den *= i64(i)
}
return num / den
}
fn faulhaber_triangle(p int) []fractions.Fraction {
mut coeffs := []fractions.Fraction{len: p+1}
q := fractions.fraction(1, i64(p)+1)
mut t := fractions.fraction(1,1)
mut u := fractions.fraction(1,1)
mut sign := -1
for j,_ in coeffs {
sign *= -1
mut d := coeffs[p-j]
t=fractions.fraction(i64(sign),1)
u = fractions.fraction(binomial(p+1, j),1)
d=q*t
d*=u
d*=bernoulli(j)
coeffs[p-j]=d
}
return coeffs
}
fn main() {
for i in 0..10 {
coeffs := faulhaber_triangle(i)
for coeff in coeffs {
print("${coeff:5} ")
}
println('')
}
println('')
}

View file

@ -0,0 +1,150 @@
Module Module1
Class Frac
Private ReadOnly num As Long
Private ReadOnly denom As Long
Public Shared ReadOnly ZERO = New Frac(0, 1)
Public Shared ReadOnly ONE = New Frac(1, 1)
Public Sub New(n As Long, d As Long)
If d = 0 Then
Throw New ArgumentException("d must not be zero")
End If
Dim nn = n
Dim dd = d
If nn = 0 Then
dd = 1
ElseIf dd < 0 Then
nn = -nn
dd = -dd
End If
Dim g = Math.Abs(Gcd(nn, dd))
If g > 1 Then
nn /= g
dd /= g
End If
num = nn
denom = dd
End Sub
Private Shared Function Gcd(a As Long, b As Long) As Long
If b = 0 Then
Return a
Else
Return Gcd(b, a Mod b)
End If
End Function
Public Shared Operator -(self As Frac) As Frac
Return New Frac(-self.num, self.denom)
End Operator
Public Shared Operator +(lhs As Frac, rhs As Frac) As Frac
Return New Frac(lhs.num * rhs.denom + lhs.denom * rhs.num, rhs.denom * lhs.denom)
End Operator
Public Shared Operator -(lhs As Frac, rhs As Frac) As Frac
Return lhs + -rhs
End Operator
Public Shared Operator *(lhs As Frac, rhs As Frac) As Frac
Return New Frac(lhs.num * rhs.num, lhs.denom * rhs.denom)
End Operator
Public Shared Operator <(lhs As Frac, rhs As Frac) As Boolean
Dim x = lhs.num / lhs.denom
Dim y = rhs.num / rhs.denom
Return x < y
End Operator
Public Shared Operator >(lhs As Frac, rhs As Frac) As Boolean
Dim x = lhs.num / lhs.denom
Dim y = rhs.num / rhs.denom
Return x > y
End Operator
Public Shared Operator =(lhs As Frac, rhs As Frac) As Boolean
Return lhs.num = rhs.num AndAlso lhs.denom = rhs.denom
End Operator
Public Shared Operator <>(lhs As Frac, rhs As Frac) As Boolean
Return lhs.num <> rhs.num OrElse lhs.denom <> rhs.denom
End Operator
Public Overrides Function ToString() As String
If denom = 1 Then
Return num.ToString
Else
Return String.Format("{0}/{1}", num, denom)
End If
End Function
Public Overrides Function Equals(obj As Object) As Boolean
Dim frac = CType(obj, Frac)
Return Not IsNothing(frac) AndAlso num = frac.num AndAlso denom = frac.denom
End Function
End Class
Function Bernoulli(n As Integer) As Frac
If n < 0 Then
Throw New ArgumentException("n may not be negative or zero")
End If
Dim a(n + 1) As Frac
For m = 0 To n
a(m) = New Frac(1, m + 1)
For j = m To 1 Step -1
a(j - 1) = (a(j - 1) - a(j)) * New Frac(j, 1)
Next
Next
' returns 'first' Bernoulli number
If n <> 1 Then
Return a(0)
Else
Return -a(0)
End If
End Function
Function Binomial(n As Integer, k As Integer) As Integer
If n < 0 OrElse k < 0 OrElse n < k Then
Throw New ArgumentException()
End If
If n = 0 OrElse k = 0 Then
Return 1
End If
Dim num = 1
For i = k + 1 To n
num *= i
Next
Dim denom = 1
For i = 2 To n - k
denom *= i
Next
Return num \ denom
End Function
Function FaulhaberTriangle(p As Integer) As Frac()
Dim coeffs(p + 1) As Frac
For i = 1 To p + 1
coeffs(i - 1) = Frac.ZERO
Next
Dim q As New Frac(1, p + 1)
Dim sign = -1
For j = 0 To p
sign *= -1
coeffs(p - j) = q * New Frac(sign, 1) * New Frac(Binomial(p + 1, j), 1) * Bernoulli(j)
Next
Return coeffs
End Function
Sub Main()
For i = 1 To 10
Dim coeffs = FaulhaberTriangle(i - 1)
For Each coeff In coeffs
Console.Write("{0,5} ", coeff)
Next
Console.WriteLine()
Next
End Sub
End Module

View file

@ -0,0 +1,61 @@
import "/fmt" for Fmt
import "/math" for Int
import "/big" for BigRat
var bernoulli = Fn.new { |n|
if (n < 0) Fiber.abort("Argument must be non-negative")
var a = List.filled(n+1, null)
for (m in 0..n) {
a[m] = BigRat.new(1, m+1)
var j = m
while (j >= 1) {
a[j-1] = (a[j-1] - a[j]) * BigRat.new(j, 1)
j = j - 1
}
}
return (n != 1) ? a[0] : -a[0] // 'first' Bernoulli number
}
var binomial = Fn.new { |n, k|
if (n < 0 || k < 0) Fiber.abort("Arguments must be non-negative integers")
if (n < k) Fiber.abort("The second argument cannot be more than the first.")
if (n == k) return 1
var prod = 1
var i = n - k + 1
while (i <= n) {
prod = prod * i
i = i + 1
}
return prod / Int.factorial(k)
}
var faulhaberTriangle = Fn.new { |p|
var coeffs = List.filled(p+1, null)
var q = BigRat.new(1, p+1)
var sign = -1
for (j in 0..p) {
sign = sign * -1
var b = BigRat.new(binomial.call(p+1, j), 1)
coeffs[p-j] = q * BigRat.new(sign, 1) * b * bernoulli.call(j)
}
return coeffs
}
BigRat.showAsInt = true
for (i in 0..9) {
var coeffs = faulhaberTriangle.call(i)
for (coeff in coeffs) Fmt.write("$5s ", coeff)
System.print()
}
System.print()
// get coeffs for (k + 1)th row
var k = 17
var cc = faulhaberTriangle.call(k)
var n = BigRat.new(1000, 1)
var np = BigRat.one
var sum = BigRat.zero
for (c in cc) {
np = np * n
sum = sum + np*c
}
System.print(sum)

View file

@ -0,0 +1,9 @@
foreach p in (10){
faulhaberFormula(p).apply("%7s".fmt).concat().println();
}
// each term of faulhaberFormula is BigInt/BigInt
[1..].zipWith(fcn(n,rat){ rat*BN(1000).pow(n) }, faulhaberFormula(17))
.walk() // -->(0, -3617/60 * 1000^2, 0, 595/3 * 1000^4 ...)
.reduce('+) // rat + rat + ...
.println();