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() : num(0), denom(1) {} |
|||
⚫ | |||
if (d == 0) { |
if (d == 0) { |
||
throw |
throw std::runtime_error("d must not be zero"); |
||
} |
} |
||
int sign_of_d = d < 0 ? -1 : 1; |
|||
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); |
||
} |
} |
||
Frac operator*(int rhs) const { |
|||
⚫ | |||
static Frac ZERO() { |
|||
⚫ | |||
} |
} |
||
friend std::ostream& operator<<(std::ostream&, const Frac&); |
|||
private: |
private: |
||
int num; |
|||
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 |
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]) * |
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 |
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 * |
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 |
for (auto frac : coeffs) { |
||
cout << right << setw(5) << |
std::cout << std::right << std::setw(5) << frac << " "; |
||
} |
} |
||
cout << endl; |
std::cout << std::endl; |
||
} |
} |
||
return 0; |
return 0; |
||
}</lang> |
}</lang> |