Fraction 分数类

默认假分数,可自行修改

由于concept的原因
template <typename T>
concept is_float_v = std::is_floating_point<T>::value;
template <typename T>
concept arithmetic = std::is_arithmetic<T>::value;

需要c++20,若要c++17可用enable来替代

前两个define是是否总是约分是否检查上溢的开关

Code
// C++20
#include <cassert>
#include <cmath>
#include <concepts>
#include <cstdlib>
#include <iostream>
#include <sstream>
#include <stdexcept>
#include <string>
#include <type_traits> //#define Always_Reduce
//#define Check_Overflow #ifdef Check_Overflow
#define Check_Add_Overflow(a, b) assert(((a) + (b) - (b)) == (a))
#define Check_Mul_Overflow(a, b) assert(((a) * (b) / (b)) == (a))
#else
#define Check_Add_Overflow(a, b) 114514
#define Check_Mul_Overflow(a, b) 114514
#endif template <std::integral T>
inline T gcd(T a, T b) {
assert((a >= 0) && (b >= 0));
if (a == 0) return b;
if (b == 0) return a;
T r;
while (r = a % b) a = b, b = r;
return b;
} template <typename T>
concept is_float_v = std::is_floating_point<T>::value;
template <typename T>
concept arithmetic = std::is_arithmetic<T>::value; class Fraction {
private:
bool m_minus;
long long m_numerator;
long long m_denominator; public:
Fraction() : m_minus(false), m_numerator(0), m_denominator(1) {}
Fraction(long long numerator, long long denominator)
: m_numerator(std::abs(numerator)), m_denominator(std::abs(denominator)), m_minus((numerator < 0) ^ (denominator < 0)) {
assert(m_denominator != 0);
reduce();
}
explicit Fraction(std::string x) {
try {
std::stold(x);
} catch (std::exception e) {
std::stringstream msg;
msg << "The argument \"std::string x\"(" << x << ") is invalid";
throw std::runtime_error(msg.str());
}
std::stringstream number;
int digits = 0;
bool flag = false;
int len = x.size();
for (int i = 0; i < len; ++i) {
const auto& c = x[i];
if (i == 0) {
m_minus = (c == '-');
if (c == '-') continue;
}
if (c == '.') {
flag = true;
continue;
}
number << c;
if (flag) ++digits;
}
m_numerator = std::stoll(number.str());
m_denominator = 1;
long long base = 10;
for (; digits; digits >>= 1, base *= base)
if (digits & 1) m_denominator *= base;
reduce();
}
Fraction(const Fraction& frac) : m_numerator(frac.m_numerator), m_denominator(frac.m_denominator), m_minus(frac.m_minus) {}
template <is_float_v T>
Fraction(T x) : Fraction(std::to_string(x)) {}
template <std::integral T>
Fraction(T x) : m_minus(x < 0), m_numerator(std::abs(x)), m_denominator(1) {}
~Fraction() {} void set(long long numerator, long long denominator) {
m_minus = (numerator < 0) ^ (denominator < 0);
m_numerator = std::abs(numerator), m_denominator = std::abs(denominator);
reduce();
}
void set_numerator(long long numerator) {
m_minus = m_minus ^ (numerator < 0);
m_numerator = std::abs(numerator);
reduce();
}
void set_Denominator(long long denominator) {
assert(denominator != 0);
m_minus = m_minus ^ (denominator < 0);
m_denominator = std::abs(denominator);
reduce();
}
void set_sign(bool flag) { m_minus = m_minus ^ (flag == 0); } Fraction operator-() const { return Fraction((m_minus ? 1 : -1) * m_numerator, m_denominator); }
Fraction operator~() const { return Fraction((m_minus ? -1 : 1) * m_denominator, m_numerator); }
Fraction operator+(const Fraction& frac) const {
long long mu = m_denominator * frac.DenominatorPart();
long long t1 = m_numerator * frac.DenominatorPart(), t2 = frac.NumeratorPart() * m_denominator;
Check_Add_Overflow(t1, t2);
Check_Mul_Overflow(m_numerator, frac.DenominatorPart());
Check_Mul_Overflow(m_denominator, frac.NumeratorPart());
Check_Mul_Overflow(m_denominator, frac.DenominatorPart());
long long t = t1 + t2;
#ifdef Always_Reduce
long long g = std::abs(gcd(t, mu));
return Fraction(t / g, mu / g);
#endif
return Fraction(t, mu);
}
Fraction operator-(const Fraction& frac) { return (*this) + (-frac); }
Fraction operator*(const Fraction& frac) {
long long z = m_numerator * frac.NumeratorPart(), m = m_denominator * frac.DenominatorPart();
Check_Mul_Overflow(m_numerator, frac.NumeratorPart());
Check_Mul_Overflow(m_denominator, frac.DenominatorPart());
#ifdef Always_Reduce
long long g = gcd(z, m);
return Fraction((m_minus ^ (frac.SignPart() == 0) ? -1ll : 1ll) * z / g, m / g);
#endif
return Fraction((m_minus ^ (frac.SignPart() == 0) ? -1ll : 1ll) * z, m);
}
Fraction operator/(const Fraction& frac) { return (*this) * (~frac); }
Fraction& operator*=(const Fraction& frac) { return (*this) = (*this) * frac; }
Fraction& operator/=(const Fraction& frac) { return (*this) = (*this) / frac; }
Fraction& operator+=(const Fraction& frac) { return (*this) = (*this) + frac; }
Fraction& operator-=(const Fraction& frac) { return (*this) = (*this) - frac; } template <arithmetic T>
friend Fraction& operator+(T x, const Fraction& frac) { return frac + x; }
template <arithmetic T>
friend Fraction& operator-(T x, const Fraction& frac) { return -(frac - x); }
template <arithmetic T>
friend Fraction& operator*(T x, const Fraction& frac) { return frac * x; }
template <arithmetic T>
friend Fraction& operator/(T x, const Fraction& frac) { return ~(frac / x); } friend long long compare(const Fraction& a, const Fraction& b) {
long long t1 = a.SignPart() * a.NumeratorPart() * b.DenominatorPart();
long long t2 = b.SignPart() * b.NumeratorPart() * a.DenominatorPart();
Check_Add_Overflow(t1, t2);
Check_Mul_Overflow(a.NumeratorPart(), b.DenominatorPart());
Check_Mul_Overflow(b.NumeratorPart(), a.DenominatorPart());
return t1 - t2;
}
friend bool operator==(const Fraction& left, const Fraction& right) { return compare(left, right) == 0; }
friend bool operator!=(const Fraction& left, const Fraction& right) { return compare(left, right) != 0; }
friend bool operator>(const Fraction& left, const Fraction& right) { return compare(left, right) > 0; }
friend bool operator<(const Fraction& left, const Fraction& right) { return compare(left, right) < 0; }
friend bool operator>=(const Fraction& left, const Fraction& right) { return compare(left, right) >= 0; }
friend bool operator<=(const Fraction& left, const Fraction& right) { return compare(left, right) <= 0; } [[nodiscard]] inline long long NumeratorPart() const { return m_numerator; }
[[nodiscard]] inline long long DenominatorPart() const { return m_denominator; }
[[nodiscard]] inline bool SignPart() const { return !m_minus; }
[[nodiscard]] long long IntegerPart() const { return m_numerator / m_denominator; }
[[nodiscard]] std::pair<long long, long long> FractionPart() const { return {m_numerator % m_denominator, m_denominator}; } [[nodiscard]] float toFloat() const { return static_cast<float>(toLDouble()); }
[[nodiscard]] double toDouble() const { return static_cast<double>(toLDouble()); }
[[nodiscard]] long double toLDouble() const { return static_cast<long double>(m_minus ? -1.0 : 1.0) * m_numerator / m_denominator; } friend std::ostream& operator<<(std::ostream& os, const Fraction& frac) {
if (frac.m_minus) os << '-';
os << frac.m_numerator << "/" << frac.m_denominator;
return os;
}
inline void reduce() {
#ifdef Always_Reduce
auto tmp = std::abs(gcd(m_numerator, m_denominator));
m_numerator /= tmp, m_denominator /= tmp;
#endif
}
};
Fraction pow(Fraction f, long long b) {
Fraction ret(1ll);
for (; b; b >>= 1, f = f * f)
if (b & 1) ret = f * ret;
return ret;
}

封装Fraction-分数类(C++)的更多相关文章

  1. Problem F: 分数类的类型转换

    Description 封装一个分数类Fract,用来处理分数功能和运算,支持以下操作:   1. 构造:传入两个参数n和m,表示n/m:分数在构造时立即转化成最简分数. 2. show()函数:分数 ...

  2. Problem E: 分数类的输出

    Problem E: 分数类的输出 Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 2699  Solved: 1227[Submit][Status][ ...

  3. UVA 10288 Coupons---概率 && 分数类模板

    题目链接: https://cn.vjudge.net/problem/UVA-10288 题目大意: 一种刮刮卡一共有n种图案,每张可刮出一个图案,收集n种就有奖,问平均情况下买多少张才能中奖?用最 ...

  4. 【作品】超实用C++分数类

    引言 我们说,编程语言的精髓在于封装,而面向对象语言完胜面向过程语言的原因就是具有更好的可封装性,而C++就是这样的一种多范型语言,常用而复杂的工作完全不必在每一份源文件中重敲,就好像我们不需要自己手 ...

  5. OC2_分数类

    // // Fraction.h // OC2_分数类 // // Created by zhangxueming on 15/6/10. // Copyright (c) 2015年 zhangxu ...

  6. 第十七周oj刷题——Problem B: 分数类的四则运算【C++】

    Description 编写分数类Fraction,实现两个分数的加.减.乘和除四则运算.主函数已给定. Input 每行四个数,分别表示两个分数的分子和分母,以0 0 0 0 表示结束. Outpu ...

  7. java的分数类

    概述 分数类在算法中非常重要, 而在java中不那么重要,java基础类库提供 了biginteger了,提供类似方式, package 组合数学; public class Fraction { p ...

  8. .NET3.5中JSON用法以及封装JsonUtils工具类

    .NET3.5中JSON用法以及封装JsonUtils工具类  我们讲到JSON的简单使用,现在我们来研究如何进行封装微软提供的JSON基类,达到更加方便.简单.强大且重用性高的效果. 首先创建一个类 ...

  9. MySQL数据库学习笔记(十一)----DAO设计模式实现数据库的增删改查(进一步封装JDBC工具类)

    [声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/4 ...

随机推荐

  1. python之loggin模块与第三方模块

    目录 logging模块详解 第三方模块 openpyxl模块 logging模块详解 主要组成部分 logger对象,用于产生日志 # 第一步,创建logger对象 logger = logging ...

  2. windows和linux系统下测试端口连通性的命令

    0. ping 1. telnet 2. ssh 3. curl 4. wget 5. tcping 6. 总结 本文地址: https://www.cnblogs.com/hchengmx/p/12 ...

  3. iPhone x 的区别

    最近入手两台iPhone x, 均从官网购买,两台分别是2017年和2018年生产,对比了一下,两台还有是一些差别: 首先苹果X使用起来还是非常爽的,没有HOME键,明显比按HOME键方便,因为按HO ...

  4. generatorConfig.xml自动生成实体类,dao和xml

    <?xml version="1.0" encoding="UTF-8"?><!DOCTYPE generatorConfiguration ...

  5. 高级web网页人脸识别tracking.js

    what?你没有看错,强大的JavaScript也可以实现人脸识别功能.小编精心整理了一个人脸识别的JavaScript库(tracking.js),通过这篇文章,你可以了解到如何在网页中实现一个人脸 ...

  6. Vue.js与Node.js一起打造一款属于自己的音乐App(收藏)

    更多内容请见原文,原文转载自:https://blog.csdn.net/weixin_44519496/article/details/118755888

  7. idea显示 RunDashboard ,多个启动项时列表显示

    在.idea(项目所在文件夹中)下的workspace.xml文件中找到 <component name="RunDashboard"> 标签,然后添加如下节点 < ...

  8. 11.4 Android Studio如何设置代理

    有些网络环境下,Android Studio下载无法下载依赖,这个时候就要配置代理,至于代理的问题,大家要自己解决. 获取代理信息 一般要获取如下信息: 地址:可以是域名和IP 端口: 代理类型:常用 ...

  9. Vite+TS带你搭建一个属于自己的Vue3组件库

    theme: nico 前言 随着前端技术的发展,业界涌现出了许多的UI组件库.例如我们熟知的ElementUI,Vant,AntDesign等等.但是作为一个前端开发者,你知道一个UI组件库是如何被 ...

  10. CTCLoss如何使用

    CTCLoss如何使用 目录 CTCLoss如何使用 什么是CTC 架构介绍 一个简单的例子 CTC计算的推导 总概率\(p(z|x)\) 路径的含义 路径概率\(p(\pi|x)\) 什么是\(\m ...