Faulhaber's triangle: Difference between revisions

Content added Content deleted
m (→‎{{header|Python}}: Pruned one import, updated primitives, tidied.)
(→‎{{header|C++}}: Some clean up)
Line 387: Line 387:
#include <sstream>
#include <sstream>
#include <vector>
#include <vector>

class Frac {
class Frac {
public:
public:

Frac(long n, long d) {
Frac() : num(0), denom(1) {}

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


long nn = n;
int sign_of_d = d < 0 ? -1 : 1;
long dd = d;
int g = std::gcd(n, d);
if (nn == 0) {
dd = 1;
} else if (dd < 0) {
nn = -nn;
dd = -dd;
}


num = sign_of_d * n / g;
long g = abs(std::gcd(nn, dd));
denom = sign_of_d * d / g;
if (g > 1) {
nn /= g;
dd /= g;
}

num = nn;
denom = dd;
}
}

Frac operator-() const {
Frac operator-() const {
return Frac(-num, denom);
return Frac(-num, denom);
}
}

Frac operator+(const Frac& rhs) const {
Frac operator+(const Frac& rhs) const {
return Frac(num*rhs.denom + denom * rhs.num, rhs.denom*denom);
return Frac(num*rhs.denom + denom * rhs.num, rhs.denom*denom);
}
}

Frac operator-(const Frac& rhs) const {
Frac operator-(const Frac& rhs) const {
return Frac(num*rhs.denom - denom * rhs.num, rhs.denom*denom);
return Frac(num*rhs.denom - denom * rhs.num, rhs.denom*denom);
}
}

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


friend std::ostream& operator<<(std::ostream&, const Frac&);
Frac operator*(int rhs) const {
return Frac(num * rhs, denom);

static Frac ZERO() {
return Frac(0, 1);
}
}


friend std::ostream& operator<<(std::ostream&, const Frac&);
private:
private:
long num;
int num;
long denom;
int denom;
};
};

std::ostream & operator<<(std::ostream & os, const Frac &f) {
std::ostream & operator<<(std::ostream & os, const Frac &f) {
if (f.num == 0 || f.denom == 1) {
if (f.num == 0 || f.denom == 1) {
return os << f.num;
return os << f.num;
}
}

std::stringstream ss;
std::stringstream ss;
ss << f.num << "/" << f.denom;
ss << f.num << "/" << f.denom;
return os << ss.str();
return os << ss.str();
}
}

Frac bernoulli(int n) {
Frac bernoulli(int n) {
if (n < 0) {
if (n < 0) {
throw new std::runtime_error("n may not be negative or zero");
throw std::runtime_error("n may not be negative or zero");
}
}

std::vector<Frac> a;
std::vector<Frac> a;
for (int m = 0; m <= n; m++) {
for (int m = 0; m <= n; m++) {
a.push_back(Frac(1, m + 1));
a.push_back(Frac(1, m + 1));
for (int j = m; j >= 1; j--) {
for (int j = m; j >= 1; j--) {
a[j - 1] = (a[j - 1] - a[j]) * Frac(j, 1);
a[j - 1] = (a[j - 1] - a[j]) * j;
}
}
}
}

// returns 'first' Bernoulli number
// returns 'first' Bernoulli number
if (n != 1) return a[0];
if (n != 1) return a[0];
return -a[0];
return -a[0];
}
}

int binomial(int n, int k) {
int binomial(int n, int k) {
if (n < 0 || k < 0 || n < k) {
if (n < 0 || k < 0 || n < k) {
throw new std::runtime_error("parameters are invalid");
throw std::runtime_error("parameters are invalid");
}
}
if (n == 0 || k == 0) return 1;
if (n == 0 || k == 0) return 1;

int num = 1;
int num = 1;
for (int i = k + 1; i <= n; i++) {
for (int i = k + 1; i <= n; i++) {
num *= i;
num *= i;
}
}

int denom = 1;
int denom = 1;
for (int i = 2; i <= n - k; i++) {
for (int i = 2; i <= n - k; i++) {
denom *= i;
denom *= i;
}
}

return num / denom;
return num / denom;
}
}

std::vector<Frac> faulhaberTraingle(int p) {
std::vector<Frac> faulhaberTraingle(int p) {
std::vector<Frac> coeffs;
std::vector<Frac> coeffs(p + 1);

for (int i = 0; i < p + 1; i++) {
coeffs.push_back(Frac::ZERO());
}

Frac q{ 1, p + 1 };
Frac q{ 1, p + 1 };
int sign = -1;
int sign = -1;
for (int j = 0; j <= p; j++) {
for (int j = 0; j <= p; j++) {
sign *= -1;
sign *= -1;
coeffs[p - j] = q * Frac(sign, 1) * Frac(binomial(p + 1, j), 1) * bernoulli(j);
coeffs[p - j] = q * sign * binomial(p + 1, j) * bernoulli(j);
}
}

return coeffs;
return coeffs;
}
}

int main() {
int main() {
using namespace std;

for (int i = 0; i < 10; i++) {
for (int i = 0; i < 10; i++) {
vector<Frac> coeffs = faulhaberTraingle(i);
std::vector<Frac> coeffs = faulhaberTraingle(i);
for (auto it = coeffs.begin(); it != coeffs.end(); it++) {
for (auto frac : coeffs) {
cout << right << setw(5) << *it << " ";
std::cout << std::right << std::setw(5) << frac << " ";
}
}
cout << endl;
std::cout << std::endl;
}
}

return 0;
return 0;
}</lang>
}</lang>