競技プログラミング用にC++で分数を扱えるクラスを作りました
(処理速度は考えてません
参考
- http://blog.livedoor.jp/add20/archives/2285655.html
- http://www002.upp.so-net.ne.jp/ys_oota/effec/chapter4.htm
コードは下記(# コード)
- 2019/07/25 var.1.0.0
- 2019/07/27 var.1.1.0
- swap()などをstdを使用するように変更
- dight()を削除
-
Fraction operator+(long long b);
などを削除 - 四則演算の順序が逆でもできるように変更
内容
Fraction a(2, 5);
で、2/5という分数のクラスを作成することができます
また
Fraction a(3);
で、3( = 3/1)を作成できます
一応、四則演算等は使用できます
toString()
でStringに、toLongDouble()
でlong doubleに変換できます
メモ
- 四則演算の相手がint型であっても、コンパイラが自動的にintをFractionに変換してくれる
- 四則演算の順序について(aはFraction型)
Fraction operator*(const Fraction& b);
だと、a * 2しかできないが、
friend const Fraction operator*(const Fraction& a, const Fraction& b);
にして、色々すると、2 * aもできるようになる
コード
Fraction.h
Fraction.h
#include <string>
#pragma once
class Fraction
{
private:
long long numer; // 分子
long long denom; // 分母
friend const bool operator==(const Fraction& a, const Fraction& b);
friend const bool operator!=(const Fraction& a, const Fraction& b);
friend const bool operator>=(const Fraction& a, const Fraction& b);
friend const bool operator<=(const Fraction& a, const Fraction& b);
friend const bool operator>(const Fraction& a, const Fraction& b);
friend const bool operator<(const Fraction& a, const Fraction& b);
friend const Fraction operator+(const Fraction& a, const Fraction& b);
friend const Fraction operator-(const Fraction& a, const Fraction& b);
friend const Fraction operator*(const Fraction& a, const Fraction& b);
friend const Fraction operator/(const Fraction& a, const Fraction& b);
public:
Fraction();
Fraction(long long);
Fraction(long long, long long);
Fraction(const Fraction&);
void set(long long, long long);
void set(const Fraction&);
void setNumer(long long);
void setDenom(long long);
long long getNumer();
long long getDenom();
static long long gcd(long long, long long); // 最大公約数
static long long lcm(long long, long long); // 最小公倍数
void normal(); // 約分
std::string toString();
long double toLongDouble();
bool equals(const Fraction&) const;
long long compare(const Fraction&) const;
Fraction& operator=(const Fraction& b);
Fraction& operator+=(const Fraction& b);
Fraction& operator-=(const Fraction& b);
Fraction& operator*=(const Fraction& b);
Fraction& operator/=(const Fraction& b);
Fraction operator+();
Fraction operator-();
Fraction& operator++();
Fraction operator++(int);
Fraction& operator--();
Fraction operator--(int);
};
Fraction.cpp
Fraction.cpp
#include "Fraction.h"
#include <utility>
long long Fraction::gcd(long long a, long long b)
{
a = abs(a);
b = abs(b);
if (a < b) std::swap(a, b);
long long tmp;
while (b != 0) {
tmp = b;
b = a % b;
a = tmp;
}
return a;
}
long long Fraction::lcm(long long a, long long b)
{
a = abs(a);
b = abs(b);
if (a > b) std::swap(a, b);
if (a == 1) return b;
long long i = a;
while (i % b != 0)
{
i += a;
}
return i;
}
Fraction::Fraction()
{
set(0, 1);
}
Fraction::Fraction(long long n)
{
set(n, 1);
}
Fraction::Fraction(long long numer, long long denom)
{
set(numer, denom);
}
Fraction::Fraction(const Fraction& b)
{
set(b);
}
void Fraction::set(long long numer, long long denom)
{
this->numer = numer;
this->denom = denom;
normal();
}
void Fraction::set(const Fraction& b)
{
this->numer = b.numer;
this->denom = b.denom;
}
void Fraction::setNumer(long long numer)
{
this->numer = numer;
normal();
}
void Fraction::setDenom(long long denom)
{
this->denom = denom;
normal();
}
inline long long Fraction::getNumer()
{
return numer;
}
inline long long Fraction::getDenom()
{
return denom;
}
void Fraction::normal()
{
long long gcd = this->gcd(getNumer(), getDenom());
if (gcd == 1)
{
// 分母は常に正
if (denom < 0)
{
numer *= -1;
denom *= -1;
}
return;
}
long long numer = getNumer() / gcd;
long long denom = getDenom() / gcd;
// 分母は常に正
if (denom < 0)
{
numer *= -1;
denom *= -1;
}
set(numer, denom);
}
std::string Fraction::toString()
{
std::string str = "";
if (getDenom() == 1)
str = std::to_string(getNumer());
else
str = std::to_string(getNumer()) + "/" + std::to_string(getDenom());
return str;
}
long double Fraction::toLongDouble()
{
return (long double)getNumer() / getDenom();
}
bool Fraction::equals(const Fraction& b) const {
return numer == b.numer && denom == b.denom;
}
long long Fraction::compare(const Fraction& b) const {
long long lcm = this->lcm(denom, b.denom);
return (lcm / denom) * numer - (lcm / b.denom) * b.numer;
}
const bool operator==(const Fraction& a, const Fraction& b) { return a.equals(b); }
const bool operator!=(const Fraction& a, const Fraction& b) { return !a.equals(b); }
const bool operator>=(const Fraction& a, const Fraction& b) { return a.compare(b) >= 0; }
const bool operator<=(const Fraction& a, const Fraction& b) { return a.compare(b) <= 0; }
const bool operator>(const Fraction& a, const Fraction& b) { return a.compare(b) > 0; }
const bool operator<(const Fraction& a, const Fraction& b) { return a.compare(b) < 0; }
Fraction& Fraction::operator=(const Fraction& b) {
this->set(b);
return *this;
}
const Fraction operator+(const Fraction& a, const Fraction& b) {
long long lcm = Fraction::lcm(a.denom, b.denom);
long long numer = a.numer * (lcm / a.denom) + b.numer * (lcm / b.denom);
return Fraction(numer, lcm);
}
const Fraction operator-(const Fraction& a, const Fraction& b) {
return operator+(a, Fraction(-b.numer, b.denom));
}
const Fraction operator*(const Fraction& a, const Fraction& b) {
long long gcd = Fraction::gcd(a.numer, b.denom);
long long numer = a.numer / gcd;
long long denom = b.denom / gcd;
gcd = Fraction::gcd(b.numer, a.denom);
numer *= b.numer / gcd;
denom *= a.denom / gcd;
return Fraction(numer, denom);
}
const Fraction operator/(const Fraction& a, const Fraction& b) {
return operator*(a, Fraction(b.denom, b.numer));
}
Fraction& Fraction::operator+=(const Fraction& b) { return *this = *this + b; }
Fraction& Fraction::operator-=(const Fraction& b) { return *this = *this - b; }
Fraction& Fraction::operator*=(const Fraction& b) { return *this = *this * b; }
Fraction& Fraction::operator/=(const Fraction& b) { return *this = *this / b; }
Fraction Fraction::operator+() { return Fraction(this->numer, this->denom); };
Fraction Fraction::operator-() { return Fraction(-(this->numer), this->denom); };
Fraction& Fraction::operator++() { return *this += 1; }
Fraction& Fraction::operator--() { return *this += -1; }
Fraction Fraction::operator++(int) {
Fraction tmp = *this;
*this += 1;
return tmp;
}
Fraction Fraction::operator--(int) {
Fraction tmp = *this;
*this += -1;
return tmp;
}