分数类 frac
报喜,分数类研制成功!
正式完结散花!简单测试了下,基本没有 bug。
本代码遵循 CC-BY-NC-ND (署名-非商业使用-禁止演绎)协议。
代码:frac.h
#pragma once
#include <iostream>
#include <utility>
#include <cmath>
#if __cplusplus >= 202002L
#include <format>
#endif
constexpr long long gcd(long long a, long long b) {
return !b ? a : gcd(b, a % b);
}
constexpr long long lcm(long long a, long long b) {
return a * b / gcd(a, b);
}
template<typename _Ty1 = int, typename _Ty2 = int>
class frac {
private:
_Ty1 numerator;
_Ty2 denominator;
public:
static constexpr auto cannot{ static_cast<unsigned long long>(-1) };
frac() {
numerator = denominator = 0;
}
frac(long long _num, long long _den) {
numerator = _num;
denominator = _den;
}
frac(long long _number) {
numerator = _number;
denominator = 1;
}
frac &operator=(frac _Right) {
numerator = _Right.numerator;
denominator = _Right.denominator;
return *this;
}
frac &operator=(long long _number) {
numerator = _number;
denominator = 1;
return *this;
}
friend void reduction(frac &_Left, frac &_Right) {
long long lcmValue = lcm(_Left.denominator, _Right.denominator);
_Left.numerator *= lcmValue / _Left.denominator, _Left.denominator = lcmValue;
_Right.numerator *= lcmValue / _Right.denominator, _Right.denominator = lcmValue;
}
bool check() {
long long gcdValue = gcd(numerator, denominator);
if (gcdValue == 1) {
return 1;
}
numerator /= gcdValue, denominator /= gcdValue;
return 0;
}
friend frac operator+(frac _Left, frac _Right) {
reduction(_Left, _Right);
frac _Answer(_Left.numerator + _Right.numerator, _Left.denominator);
_Answer.check();
return _Answer;
}
friend frac operator-(frac _Left, frac _Right) {
reduction(_Left, _Right);
frac _Answer(_Left.numerator - _Right.numerator, _Left.denominator);
_Answer.check();
return _Answer;
}
friend frac operator*(frac _Left, frac _Right) {
frac _Answer(_Left.numerator * _Right.numerator, _Left.denominator * _Right.denominator);
_Answer.check();
return _Answer;
}
friend frac operator/(frac _Left, frac _Right) {
return _Left * frac(_Right.denominator, _Right.numerator);
}
frac &operator+=(frac _Right) {
*this = *this + _Right;
return *this;
}
frac &operator-=(frac _Right) {
*this = *this - _Right;
return *this;
}
frac &operator*=(frac _Right) {
*this = *this * _Right;
return *this;
}
frac &operator/=(frac _Right) {
*this = *this / _Right;
return *this;
}
constexpr long long toInt() {
return numerator % denominator == 0 ? numerator / denominator : cannot;
}
constexpr float toFloat() {
return 1.0f * numerator / denominator;
}
constexpr double toDouble() {
return 1.0 * numerator / denominator;
}
constexpr long double toLongDouble() {
if (sizeof(long double) == sizeof(double)) {
return this->toDouble();
}
return 1.0L * numerator / denominator;
}
constexpr long long getNum() {
return numerator;
}
constexpr long long getDen() {
return denominator;
}
};
bool _none = 0, _mixed = 0;
struct _NoLine {
void operator()(std::ostream &out) {
_none = 1;
}
} none;
struct _Mixed {
void operator()(std::ostream &out) {
_mixed = 1;
}
} mixed;
template<typename _Ty1 = int, typename _Ty2 = int>
std::istream &operator>>(std::istream &in, frac<_Ty1, _Ty2> &__x) {
long long _num, _den;
in >> _num >> _den;
__x = frac<_Ty1, _Ty2>(_num, _den);
__x.check();
return in;
}
std::ostream &operator<<(std::ostream &out, _NoLine __n) {
_none = 1;
return out;
}
std::ostream &operator<<(std::ostream &out, _Mixed __n) {
_mixed = 1;
return out;
}
template<typename _Ty1 = long long, typename _Ty2 = long long>
std::ostream &operator<<(std::ostream &out, frac<_Ty1, _Ty2> __x) {
__x.check();
#if __cplusplus >= 202002L
if (_mixed) {
if (__x.getNum() % __x.getDen() == 0) {
out << __x.getNum() / __x.getDen();
} else {
long long s = 0;
for (; __x.getNum() > __x.getDen(); __x -= frac(__x.getDen(), __x.getDen())) {
++s;
}
if (s == 0) {
out << std::format("{}/{}", __x.getNum(), __x.getDen());
} else {
out << std::format("{} {}/{}", s, __x.getNum(), __x.getDen());
}
}
_mixed = 0;
} else if (_none) {
out << std::format("{} {}", __x.getNum(), __x.getDen());
_none = 0;
} else {
out << std::format("{}/{}", __x.getNum(), __x.getDen());
}
#else
if (_mixed) {
if (__x.getNum() % __x.getDen() == 0) {
out << __x.getNum() / __x.getDen();
} else {
long long s = 0;
for (; __x.getNum() > __x.getDen(); __x -= frac<_Ty1, _Ty2>(__x.getDen(), __x.getDen())) {
++s;
}
if (s == 0) {
out << __x.getNum() << '/' << __x.getDen();
} else {
out << s << ' ' << __x.getNum() << '/' << __x.getDen();
}
}
_mixed = 0;
} else if (_none) {
out << __x.getNum() << ' ' << __x.getDen();
_none = 0;
} else {
if (__x.toInt() != frac<_Ty1, _Ty2>::cannot) {
out << __x.toInt();
} else {
out << __x.getNum() << '/' << __x.getDen();
}
}
#endif
return out;
}
主函数代码
#include "frac.h"
#include <iostream>
using namespace std;
int main() {
frac<int, int> a(7, 9);
cout << a + frac<int, int>(4, 18) << '\n';
return 0;
}
输出
1

浙公网安备 33010602011771号