Console Library 4.7.0
A header-only library that makes C++ simple
Loading...
Searching...
No Matches
rational.h
Go to the documentation of this file.
1
11
12/*
13Copyright (c) 2026 MrXie1109
14
15Permission is hereby granted, free of charge, to any person obtaining a copy
16of this software and associated documentation files (the "Software"), to deal
17in the Software without restriction, including without limitation the rights
18to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
19copies of the Software, and to permit persons to whom the Software is
20furnished to do so, subject to the following conditions:
21
22The above copyright notice and this permission notice shall be included in all
23copies or substantial portions of the Software.
24
25THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
28AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
29LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
30OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31SOFTWARE.
32*/
33
34#pragma once
35#include <cstdint>
36#include <cmath>
37#include <cstdlib>
38#include <iostream>
39#include <type_traits>
40#include "csexc.h"
41
42namespace console
43{
49 template <class T>
51 {
52 static_assert(std::is_integral<T>::value &&
53 std::is_signed<T>::value,
54 "T must be signed integral type");
55
56 T num;
57 T den;
58
65 static T gcd(T a, T b)
66 {
67 a = std::abs(a);
68 b = std::abs(b);
69 while (b != 0)
70 {
71 T temp = b;
72 b = a % b;
73 a = temp;
74 }
75 return a;
76 }
77
82 void reduce()
83 {
84 if (den == 0)
85 {
86 throw domain_error("Denominator cannot be zero");
87 }
88 if (den < 0)
89 {
90 num = -num;
91 den = -den;
92 }
93 T g = gcd(num, den);
94 num /= g;
95 den /= g;
96 }
97
98 public:
100 constexpr BasicRational() : num(0), den(1) {}
101
106 constexpr BasicRational(T n) : num(n), den(1) {}
107
115 BasicRational(T n, T d) : num(n), den(d) { reduce(); }
116
121 T numerator() const { return num; }
122
127 T denominator() const { return den; }
128
134 template <class U>
135 explicit operator U() const { return U(num) / den; }
136
145 const BasicRational &lhs, const BasicRational &rhs)
146 {
147 return BasicRational(lhs.num * rhs.den + rhs.num * lhs.den,
148 lhs.den * rhs.den);
149 }
150
159 const BasicRational &lhs, const BasicRational &rhs)
160 {
161 return BasicRational(lhs.num * rhs.den - rhs.num * lhs.den,
162 lhs.den * rhs.den);
163 }
164
173 const BasicRational &lhs, const BasicRational &rhs)
174 {
175 return BasicRational(lhs.num * rhs.num, lhs.den * rhs.den);
176 }
177
187 const BasicRational &lhs, const BasicRational &rhs)
188 {
189 if (rhs.num == 0)
190 throw domain_error("Division by zero");
191 return BasicRational(lhs.num * rhs.den, lhs.den * rhs.num);
192 }
193
200 {
201 *this = *this + other;
202 return *this;
203 }
204
211 {
212 *this = *this - other;
213 return *this;
214 }
215
222 {
223 *this = *this * other;
224 return *this;
225 }
226
234 {
235 *this = *this / other;
236 return *this;
237 }
238
243 BasicRational operator-() const { return BasicRational(-num, den); }
244
249 BasicRational operator+() const { return *this; }
250
257 friend bool operator==(
258 const BasicRational &lhs, const BasicRational &rhs)
259 {
260 return lhs.num == rhs.num && lhs.den == rhs.den;
261 }
262
269 friend bool operator!=(
270 const BasicRational &lhs, const BasicRational &rhs)
271 {
272 return !(lhs == rhs);
273 }
274
281 friend bool operator<(
282 const BasicRational &lhs, const BasicRational &rhs)
283 {
284 return lhs.num * rhs.den < rhs.num * lhs.den;
285 }
286
293 friend bool operator>(
294 const BasicRational &lhs, const BasicRational &rhs)
295 {
296 return rhs < lhs;
297 }
298
305 friend bool operator<=(
306 const BasicRational &lhs, const BasicRational &rhs)
307 {
308 return !(lhs > rhs);
309 }
310
317 friend bool operator>=(
318 const BasicRational &lhs, const BasicRational &rhs)
319 {
320 return !(lhs < rhs);
321 }
322
329 friend std::ostream &operator<<(std::ostream &os, const BasicRational &r)
330 {
331 os << intmax_t(r.num);
332 if (r.den != 1)
333 os << '/' << intmax_t(r.den);
334 return os;
335 }
336
344 friend std::istream &operator>>(std::istream &is, BasicRational &r)
345 {
346 intmax_t n, d;
347 char slash;
348 is >> n;
349 if (is >> std::ws, is.peek() == '/')
350 {
351 is >> slash >> d;
352 r = BasicRational(intmax_t(n), intmax_t(d));
353 }
354 else
355 r = BasicRational(intmax_t(n));
356 return is;
357 }
358 };
359
365}
用于表示分数的基础模板类。
Definition rational.h:51
T numerator() const
取得分数的分子。
Definition rational.h:121
constexpr BasicRational()
默认构造函数,构造一个值为 0/1 的分数。
Definition rational.h:100
friend bool operator>=(const BasicRational &lhs, const BasicRational &rhs)
比较左操作数是否大于等于右操作数(ge)。
Definition rational.h:317
friend std::ostream & operator<<(std::ostream &os, const BasicRational &r)
将一个分数打印到指定输出流。
Definition rational.h:329
friend BasicRational operator*(const BasicRational &lhs, const BasicRational &rhs)
计算两个分数的积。
Definition rational.h:172
BasicRational operator-() const
返回相反数。
Definition rational.h:243
BasicRational operator+() const
返回自身。
Definition rational.h:249
friend bool operator<=(const BasicRational &lhs, const BasicRational &rhs)
比较左操作数是否小于等于右操作数(le)。
Definition rational.h:305
T denominator() const
取得分数的分母。
Definition rational.h:127
BasicRational & operator*=(const BasicRational &other)
就地版本,等价于 a = a * b。
Definition rational.h:221
friend bool operator!=(const BasicRational &lhs, const BasicRational &rhs)
比较两个分数是否不等(ne)。
Definition rational.h:269
BasicRational(T n, T d)
接受双参的构造函数,构造一个值为 n/d 的分数。
Definition rational.h:115
friend bool operator>(const BasicRational &lhs, const BasicRational &rhs)
比较左操作数是否大于右操作数(gt)。
Definition rational.h:293
BasicRational & operator+=(const BasicRational &other)
就地版本,等价于 a = a + b。
Definition rational.h:199
BasicRational & operator/=(const BasicRational &other)
就地版本,等价于 a = a / b。
Definition rational.h:233
friend BasicRational operator/(const BasicRational &lhs, const BasicRational &rhs)
计算两个分数的商。
Definition rational.h:186
friend std::istream & operator>>(std::istream &is, BasicRational &r)
从指定输入流读取一个分数。
Definition rational.h:344
friend BasicRational operator-(const BasicRational &lhs, const BasicRational &rhs)
计算两个分数的差。
Definition rational.h:158
BasicRational & operator-=(const BasicRational &other)
就地版本,等价于 a = a - b。
Definition rational.h:210
friend bool operator<(const BasicRational &lhs, const BasicRational &rhs)
比较左操作数是否小于右操作数(lt)。
Definition rational.h:281
friend bool operator==(const BasicRational &lhs, const BasicRational &rhs)
比较两个分数是否相等(eq)。
Definition rational.h:257
constexpr BasicRational(T n)
接受单参的构造函数,构造一个值为 n/1 的分数。
Definition rational.h:106
friend BasicRational operator+(const BasicRational &lhs, const BasicRational &rhs)
计算两个分数的和。
Definition rational.h:144
表示试图对无效的数学值域进行操作时抛出的异常。
Definition csexc.h:182
定义 console 库使用的自定义异常类层次结构。
本库所有组件所在的顶层命名空间。
BasicRational< int8_t > Rational_8
以 int8_t 为基的分数。
Definition rational.h:361
@ U
Definition kb.h:73
@ T
Definition kb.h:72
BasicRational< int16_t > Rational_16
以 int16_t 为基的分数。
Definition rational.h:362
BasicRational< int32_t > Rational_32
以 int32_t 为基的分数。
Definition rational.h:363
BasicRational< int64_t > Rational_64
以 int64_t 为基的分数。
Definition rational.h:364
BasicRational< intmax_t > Rational
以 intmax_t 为基的分数。
Definition rational.h:360