x011.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include "xerror.h"
4 #include "xtools.h"
5 #include <algorithm>
6 #include <cmath>
7 #include <ctime>
8 #include <iostream>
9 #include <numeric>
10 #include <string>
11 #include <sstream>
12 #include <tuple>
13 #include <type_traits>
14 #include <vector>
15 
16 namespace nmx::apps::x011 {
17 
21 class Rational
22 {
23 private:
24  long long _num, _den;
25 
26 public:
32  inline Rational(long long n = 0, long long d = 1)
33  : _num{ n }
34  , _den{ d } {
35  if (d == 0) {
36  throw std::domain_error(__func__);
37  }
38  if (d < 0) {
39  _num *= -1;
40  _den *= -1;
41  }
42  }
43 
48  inline auto num() const { return _num; }
49 
54  inline auto den() const { return _den; }
55 
59  inline void simplify() {
60  long gcd = std::gcd(_num, _den);
61  _num /= gcd;
62  _den /= gcd;
63  }
64 
68  explicit operator double() const { //
69  return static_cast<double>(_num) / static_cast<double>(_den);
70  }
71 
77  template<class T>
78  static constexpr bool is_int_like_v = //
79  (std::is_arithmetic_v<T> &&std::is_integral_v<T> //
80  && !std::is_same_v<T, bool> && !std::is_same_v<T, char>);
81 
82  // Test : ist T eine ganze oder eine rationale Zahl
83  template<class T>
84  static constexpr bool is_rational_like_v = //
85  is_int_like_v<T> || std::is_same_v<T, Rational>;
86 
92  template<class T, std::enable_if_t<is_rational_like_v<T>> * = nullptr>
93  inline Rational &operator+=(const T &r) {
94  if constexpr (is_int_like_v<T>) {
95  _num = _num + _den;
96  } else {
97  _num = _num * r._den + r._num * _den;
98  _den = _den * r._den;
99  }
100  simplify();
101  return *this;
102  }
103 
109  template<class T, std::enable_if_t<is_rational_like_v<T>> * = nullptr>
110  inline Rational &operator-=(const T &r) {
111  if constexpr (is_int_like_v<T>) {
112  _num = _num - _den;
113  } else {
114  _num = _num * r._den - r._num * _den;
115  _den = _den * r._den;
116  }
117  simplify();
118  return *this;
119  }
120 
126  template<class T, std::enable_if_t<is_rational_like_v<T>> * = nullptr>
127  inline Rational &operator*=(const T &r) {
128  if constexpr (is_int_like_v<T>) {
129  _num = _num * r;
130  } else {
131  _num *= r._num;
132  _den *= r._den;
133  }
134  simplify();
135  return *this;
136  }
137 
143  template<class T, std::enable_if_t<is_rational_like_v<T>> * = nullptr>
144  inline Rational &operator/=(const T &r) {
145  if (r.num() == 0) {
146  throw std::overflow_error("operator/=");
147  }
148  if constexpr (is_int_like_v<T>) {
149  _den *= r;
150  } else {
151  _num *= r._den;
152  _den *= r._num;
153  }
154  return *this;
155  }
156 
164  template<class X, class Y, class FN>
165  inline friend auto helpfn(const X &arg1, const Y &arg2, FN fn) {
166  //wenn eine der beiden Zahlen eine Fließkommazahl ist
167  if constexpr (std::is_floating_point_v<X> || //
168  std::is_floating_point_v<Y>) {
169  //...ist das Ergebnis auch eine Fließkommazahl
170  double rout = static_cast<double>(arg1);
171  fn(rout, static_cast<double>(arg2));
172  return rout;
173  } else {
174  Rational rout{ arg1 };
175  fn(rout, Rational{ arg2 });
176  rout.simplify();
177  return rout;
178  }
179  }
180 
185  template<class X, class Y>
186  using is_candidate_t = //
187  std::enable_if_t<std::is_same_v<X, Rational> || std::is_same_v<Y, Rational>>;
188 
193  template<class X, class Y, is_candidate_t<X, Y> * = nullptr>
194  inline friend auto operator+(const X &x, const Y &y) {
195  return helpfn(x, y, [](auto &a, const auto &b) { a += b; });
196  }
197 
198  template<class X, class Y, is_candidate_t<X, Y> * = nullptr>
199  inline friend auto operator-(const X &x, const Y &y) {
200  return helpfn(x, y, [](auto &a, const auto &b) { a -= b; });
201  }
202 
203  template<class X, class Y, is_candidate_t<X, Y> * = nullptr>
204  inline friend auto operator*(const X &x, const Y &y) {
205  return helpfn(x, y, [](auto &a, const auto &b) { a *= b; });
206  }
207 
208  template<class X, class Y, is_candidate_t<X, Y> * = nullptr>
209  inline friend auto operator/(const X &x, const Y &y) {
210  return helpfn(x, y, [](auto &a, const auto &b) { a /= b; });
211  }
212 
219  template<typename X, typename Y, is_candidate_t<X, Y> * = nullptr>
220  inline friend bool operator==(const X &x, const Y &y) { //
221  if constexpr (std::is_same_v<X, Y>) {
222  //beide Eingabeargumente sind rationale Zahlen
223  return x.num() * y.den() == x.den() * y.num();
224  } else if constexpr (std::is_same_v<Y, Rational>) {
225  return x * y.den() == y.num();
226  } else {
227  return x.num() == x.den() * y;
228  }
229  }
230 
237  template<class X, class Y, is_candidate_t<X, Y> * = nullptr>
238  inline friend bool operator!=(const X &r1, const Y &r2) { //
239  return !(r1 == r2);
240  }
241 
248  template<class T>
249  inline friend auto pow(const Rational &r, T n) { //
250  if constexpr (std::is_same_v<T, int>) {
251  Rational r1 = n > 0 ? r : inverse(r);
252  long long num = //
253  static_cast<long long>(std::pow(r1.num(), n));
254  long long den = //
255  static_cast<long long>(std::pow(r1.den(), n));
256  return Rational{ num, den };
257  } else {
258  return std::pow(static_cast<double>(r), static_cast<double>(n));
259  }
260  }
261 
267  inline friend Rational inverse(const Rational &r) { //
268  return Rational(r.den(), r.num());
269  }
270 
276  inline friend Rational operator-(const Rational &r) { //
277  return Rational(-r.num(), r.den());
278  }
279 
286  inline friend std::ostream &operator<<(std::ostream &os, const Rational &r) {
287  return os << r.num() << "/" << r.den();
288  }
289 }; //Rational
290 
294 inline void ex1() {
295  Rational r1{ 1, 2 }, r2{ 1, 3 };
296  auto rout = r1 + r2;
297  std::cout << r1 << "+" << r2 << "=" << rout << std::endl;
298  rout = r1 - r2;
299  std::cout << r1 << "-" << r2 << "=" << rout << std::endl;
300  rout = r1 * r2;
301  std::cout << r1 << "*" << r2 << "=" << rout << std::endl;
302  rout = r1 / r2;
303  std::cout << r1 << "/" << r2 << "=" << rout << std::endl;
304  Rational r5 = r1;
305  r5 += 1;
306  std::cout << r5 << std::endl;
307 }
308 
313 inline void ex2() {
314  Rational r3{ 5, 100 };
315  std::cout << r3 << std::endl;
316  r3.simplify();
317  std::cout << "simplified:" << r3 << std::endl;
318  std::cout << "as double:" << static_cast<double>(r3) << std::endl;
319 }
320 
324 inline void ex3() {
325  Rational r4{ 2, 4 };
326 
327  //Ausgabe der bool'schen Werte
328  std::cout << std::boolalpha << (r4 == Rational{ 1, 2 }) << std::endl;
329  std::cout << std::boolalpha << (r4 != Rational{ 3, 4 }) << std::endl;
330  std::cout << std::boolalpha << (r4 == 0.5) << std::endl;
331 }
332 
336 inline void ex4() {
337  Rational r4{ 2, 4 };
338  std::cout << pow(r4, 3) << std::endl;
339  std::cout << pow(r4, 3.1) << std::endl;
340 }
341 
345 inline void ex5() {
346  Rational sum{ 0, 1 };
347 
348  for (long idx = 1; idx <= 8; idx++) {
349  sum += Rational{ 1, idx };
350  }
351 
352  std::cout << sum << std::endl;
353  std::cout << static_cast<double>(sum) << std::endl;
354 }
355 
360 inline void ex6() {
361  Rational r1{ 5, 100 };
362 
363  auto c = r1 + 0.8;
364  auto c1 = 1.1 + Rational{ 2, 2 };
365 
366  std::cout << c << std::endl;
367  std::cout << c1 << std::endl;
368 }
369 
370 } // namespace nmx::apps::x011
void ex4()
ex4 Potenzierung mit ganzer und mit einer reellen Zahl
Definition: x011.h:336
auto num() const
num lese ...
Definition: x011.h:48
friend bool operator==(const X &x, const Y &y)
operator == Vergleichsoperator
Definition: x011.h:220
friend Rational operator-(const Rational &r)
negate eine rationale Zahl wird negiert
Definition: x011.h:276
friend std::ostream & operator<<(std::ostream &os, const Rational &r)
operator << Ausgabe einer rationalen Zahl
Definition: x011.h:286
void ex1()
ex1 algebraische Operationen mit rationalen Zahlen
Definition: x011.h:294
auto den() const
den lese...
Definition: x011.h:54
friend Rational inverse(const Rational &r)
invert inverse rationale Zahl
Definition: x011.h:267
friend auto operator/(const X &x, const Y &y)
Definition: x011.h:209
Rational & operator+=(const T &r)
operator +=
Definition: x011.h:93
Rational & operator/=(const T &r)
operator /=
Definition: x011.h:144
void ex3()
ex3 Anwendung der Vergleichsoperatoren
Definition: x011.h:324
Rational Klasse für rationale Zahlen.
Definition: x011.h:21
friend auto pow(const Rational &r, T n)
pow potenziere rationale Zahl
Definition: x011.h:249
std::enable_if_t< std::is_same_v< X, Rational >||std::is_same_v< Y, Rational > > is_candidate_t
Definition: x011.h:187
Rational(long long n=0, long long d=1)
Rational Konstruktor.
Definition: x011.h:32
friend auto operator+(const X &x, const Y &y)
Definition: x011.h:194
void simplify()
simplify vereinfache Bruch
Definition: x011.h:59
void ex2()
ex2 Initialisierung,Vereinfachung, Umwandlung in eine reelle Zahl
Definition: x011.h:313
void ex6()
ex6 Summe rationale Zahl mit reeller Zahl Summe ganze Zahl mit rationaler Zahl
Definition: x011.h:360
friend auto operator*(const X &x, const Y &y)
Definition: x011.h:204
static constexpr bool is_int_like_v
Definition: x011.h:78
Rational & operator-=(const T &r)
operator -=
Definition: x011.h:110
friend auto operator-(const X &x, const Y &y)
Definition: x011.h:199
void ex5()
ex5 Summe aus rationalen Zahlen
Definition: x011.h:345
friend auto helpfn(const X &arg1, const Y &arg2, FN fn)
helpfn Hilfsfunktion zur Implementierung von +,-,*,/
Definition: x011.h:165
friend bool operator!=(const X &r1, const Y &r2)
operator != Vergleichsoperator
Definition: x011.h:238
Rational & operator*=(const T &r)
operator *=
Definition: x011.h:127
static constexpr bool is_rational_like_v
Definition: x011.h:84