Fraction 分数类

默认假分数,可自行修改

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

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

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

Code
  1. // C++20
  2. #include <cassert>
  3. #include <cmath>
  4. #include <concepts>
  5. #include <cstdlib>
  6. #include <iostream>
  7. #include <sstream>
  8. #include <stdexcept>
  9. #include <string>
  10. #include <type_traits>
  11. //#define Always_Reduce
  12. //#define Check_Overflow
  13. #ifdef Check_Overflow
  14. #define Check_Add_Overflow(a, b) assert(((a) + (b) - (b)) == (a))
  15. #define Check_Mul_Overflow(a, b) assert(((a) * (b) / (b)) == (a))
  16. #else
  17. #define Check_Add_Overflow(a, b) 114514
  18. #define Check_Mul_Overflow(a, b) 114514
  19. #endif
  20. template <std::integral T>
  21. inline T gcd(T a, T b) {
  22. assert((a >= 0) && (b >= 0));
  23. if (a == 0) return b;
  24. if (b == 0) return a;
  25. T r;
  26. while (r = a % b) a = b, b = r;
  27. return b;
  28. }
  29. template <typename T>
  30. concept is_float_v = std::is_floating_point<T>::value;
  31. template <typename T>
  32. concept arithmetic = std::is_arithmetic<T>::value;
  33. class Fraction {
  34. private:
  35. bool m_minus;
  36. long long m_numerator;
  37. long long m_denominator;
  38. public:
  39. Fraction() : m_minus(false), m_numerator(0), m_denominator(1) {}
  40. Fraction(long long numerator, long long denominator)
  41. : m_numerator(std::abs(numerator)), m_denominator(std::abs(denominator)), m_minus((numerator < 0) ^ (denominator < 0)) {
  42. assert(m_denominator != 0);
  43. reduce();
  44. }
  45. explicit Fraction(std::string x) {
  46. try {
  47. std::stold(x);
  48. } catch (std::exception e) {
  49. std::stringstream msg;
  50. msg << "The argument \"std::string x\"(" << x << ") is invalid";
  51. throw std::runtime_error(msg.str());
  52. }
  53. std::stringstream number;
  54. int digits = 0;
  55. bool flag = false;
  56. int len = x.size();
  57. for (int i = 0; i < len; ++i) {
  58. const auto& c = x[i];
  59. if (i == 0) {
  60. m_minus = (c == '-');
  61. if (c == '-') continue;
  62. }
  63. if (c == '.') {
  64. flag = true;
  65. continue;
  66. }
  67. number << c;
  68. if (flag) ++digits;
  69. }
  70. m_numerator = std::stoll(number.str());
  71. m_denominator = 1;
  72. long long base = 10;
  73. for (; digits; digits >>= 1, base *= base)
  74. if (digits & 1) m_denominator *= base;
  75. reduce();
  76. }
  77. Fraction(const Fraction& frac) : m_numerator(frac.m_numerator), m_denominator(frac.m_denominator), m_minus(frac.m_minus) {}
  78. template <is_float_v T>
  79. Fraction(T x) : Fraction(std::to_string(x)) {}
  80. template <std::integral T>
  81. Fraction(T x) : m_minus(x < 0), m_numerator(std::abs(x)), m_denominator(1) {}
  82. ~Fraction() {}
  83. void set(long long numerator, long long denominator) {
  84. m_minus = (numerator < 0) ^ (denominator < 0);
  85. m_numerator = std::abs(numerator), m_denominator = std::abs(denominator);
  86. reduce();
  87. }
  88. void set_numerator(long long numerator) {
  89. m_minus = m_minus ^ (numerator < 0);
  90. m_numerator = std::abs(numerator);
  91. reduce();
  92. }
  93. void set_Denominator(long long denominator) {
  94. assert(denominator != 0);
  95. m_minus = m_minus ^ (denominator < 0);
  96. m_denominator = std::abs(denominator);
  97. reduce();
  98. }
  99. void set_sign(bool flag) { m_minus = m_minus ^ (flag == 0); }
  100. Fraction operator-() const { return Fraction((m_minus ? 1 : -1) * m_numerator, m_denominator); }
  101. Fraction operator~() const { return Fraction((m_minus ? -1 : 1) * m_denominator, m_numerator); }
  102. Fraction operator+(const Fraction& frac) const {
  103. long long mu = m_denominator * frac.DenominatorPart();
  104. long long t1 = m_numerator * frac.DenominatorPart(), t2 = frac.NumeratorPart() * m_denominator;
  105. Check_Add_Overflow(t1, t2);
  106. Check_Mul_Overflow(m_numerator, frac.DenominatorPart());
  107. Check_Mul_Overflow(m_denominator, frac.NumeratorPart());
  108. Check_Mul_Overflow(m_denominator, frac.DenominatorPart());
  109. long long t = t1 + t2;
  110. #ifdef Always_Reduce
  111. long long g = std::abs(gcd(t, mu));
  112. return Fraction(t / g, mu / g);
  113. #endif
  114. return Fraction(t, mu);
  115. }
  116. Fraction operator-(const Fraction& frac) { return (*this) + (-frac); }
  117. Fraction operator*(const Fraction& frac) {
  118. long long z = m_numerator * frac.NumeratorPart(), m = m_denominator * frac.DenominatorPart();
  119. Check_Mul_Overflow(m_numerator, frac.NumeratorPart());
  120. Check_Mul_Overflow(m_denominator, frac.DenominatorPart());
  121. #ifdef Always_Reduce
  122. long long g = gcd(z, m);
  123. return Fraction((m_minus ^ (frac.SignPart() == 0) ? -1ll : 1ll) * z / g, m / g);
  124. #endif
  125. return Fraction((m_minus ^ (frac.SignPart() == 0) ? -1ll : 1ll) * z, m);
  126. }
  127. Fraction operator/(const Fraction& frac) { return (*this) * (~frac); }
  128. Fraction& operator*=(const Fraction& frac) { return (*this) = (*this) * frac; }
  129. Fraction& operator/=(const Fraction& frac) { return (*this) = (*this) / frac; }
  130. Fraction& operator+=(const Fraction& frac) { return (*this) = (*this) + frac; }
  131. Fraction& operator-=(const Fraction& frac) { return (*this) = (*this) - frac; }
  132. template <arithmetic T>
  133. friend Fraction& operator+(T x, const Fraction& frac) { return frac + x; }
  134. template <arithmetic T>
  135. friend Fraction& operator-(T x, const Fraction& frac) { return -(frac - x); }
  136. template <arithmetic T>
  137. friend Fraction& operator*(T x, const Fraction& frac) { return frac * x; }
  138. template <arithmetic T>
  139. friend Fraction& operator/(T x, const Fraction& frac) { return ~(frac / x); }
  140. friend long long compare(const Fraction& a, const Fraction& b) {
  141. long long t1 = a.SignPart() * a.NumeratorPart() * b.DenominatorPart();
  142. long long t2 = b.SignPart() * b.NumeratorPart() * a.DenominatorPart();
  143. Check_Add_Overflow(t1, t2);
  144. Check_Mul_Overflow(a.NumeratorPart(), b.DenominatorPart());
  145. Check_Mul_Overflow(b.NumeratorPart(), a.DenominatorPart());
  146. return t1 - t2;
  147. }
  148. friend bool operator==(const Fraction& left, const Fraction& right) { return compare(left, right) == 0; }
  149. friend bool operator!=(const Fraction& left, const Fraction& right) { return compare(left, right) != 0; }
  150. friend bool operator>(const Fraction& left, const Fraction& right) { return compare(left, right) > 0; }
  151. friend bool operator<(const Fraction& left, const Fraction& right) { return compare(left, right) < 0; }
  152. friend bool operator>=(const Fraction& left, const Fraction& right) { return compare(left, right) >= 0; }
  153. friend bool operator<=(const Fraction& left, const Fraction& right) { return compare(left, right) <= 0; }
  154. [[nodiscard]] inline long long NumeratorPart() const { return m_numerator; }
  155. [[nodiscard]] inline long long DenominatorPart() const { return m_denominator; }
  156. [[nodiscard]] inline bool SignPart() const { return !m_minus; }
  157. [[nodiscard]] long long IntegerPart() const { return m_numerator / m_denominator; }
  158. [[nodiscard]] std::pair<long long, long long> FractionPart() const { return {m_numerator % m_denominator, m_denominator}; }
  159. [[nodiscard]] float toFloat() const { return static_cast<float>(toLDouble()); }
  160. [[nodiscard]] double toDouble() const { return static_cast<double>(toLDouble()); }
  161. [[nodiscard]] long double toLDouble() const { return static_cast<long double>(m_minus ? -1.0 : 1.0) * m_numerator / m_denominator; }
  162. friend std::ostream& operator<<(std::ostream& os, const Fraction& frac) {
  163. if (frac.m_minus) os << '-';
  164. os << frac.m_numerator << "/" << frac.m_denominator;
  165. return os;
  166. }
  167. inline void reduce() {
  168. #ifdef Always_Reduce
  169. auto tmp = std::abs(gcd(m_numerator, m_denominator));
  170. m_numerator /= tmp, m_denominator /= tmp;
  171. #endif
  172. }
  173. };
  174. Fraction pow(Fraction f, long long b) {
  175. Fraction ret(1ll);
  176. for (; b; b >>= 1, f = f * f)
  177. if (b & 1) ret = f * ret;
  178. return ret;
  179. }

封装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. 利用apache ftpserver搭建ftp服务器

    操作环境: win2012r2 x64 datacenter Apache FtpServer 1.2.0 Java SE Development Kit 8u333 commons-dbcp2-2. ...

  2. arts-week13

    Algorithm 992. Sort Array By Parity II - LeetCode Review https://tls.ulfheim.net/ HTTP协议图解 Tip linux ...

  3. 从MySQL全备文件中恢复单个库或者单个表

    从MySQL全备文件中恢复单个库或者单个表 提取建库语句 sed -n '/^-- Current Database: db_cms/,/^-- Current Database: `/p' back ...

  4. 200 行代码实现基于 Paxos 的 KV 存储

    前言 写完[paxos 的直观解释]之后,网友都说疗效甚好,但是也会对这篇教程中一些环节提出疑问(有疑问说明真的看懂了 ),例如怎么把只能确定一个值的 paxos 应用到实际场景中. 既然 Talk ...

  5. 107_Power Pivot员工效率监控

    博客:www.jiaopengzi.com 焦棚子的文章目录 请点击下载附件 1.背景 在劳动密集型行业中,员工效率是一个永恒的话题. 今天把零时用工的效率提升展示及效率监控建一个PP模型并输出. 达 ...

  6. 【Java】在IDEA中将Javafx项目打包成为可运行的.jar文件

    在使用Javafx制作一个图形化界面程序的时候,我遇到了打包文件的难题. 按照网上给出的解决方案构建出来的jar文件总是没有办法运行. 以下是我最终的解决方案. 我使用的IDE是IntelliJ ID ...

  7. LC T668笔记 & 有关二分查找、第K小数、BFPRT算法

    LC T668笔记 [涉及知识:二分查找.第K小数.BFPRT算法] [以下内容仅为本人在做题学习中的所感所想,本人水平有限目前尚处学习阶段,如有错误及不妥之处还请各位大佬指正,请谅解,谢谢!] !! ...

  8. AR Engine运动跟踪能力,高精度实现沉浸式AR体验

    随着电子产品的普遍应用,AR技术也开始广泛普及,在游戏.电商.家装等领域都有涉及.比如,在室内设计时,我们可以通过AR技术在实际场景中进行虚拟软装的搭配,运用华为AR Engine运动跟踪能力在实际应 ...

  9. c++ 超长整数乘法 高精度乘法

    c++ 超长整数乘法 高精度乘法 解题思路 参考加法和减法解题思路 乘法不是一位一位的按照手算的方式进行计算,而是用循环用一个数的某一位去乘另外一个数 打卡代码 #include<bits/st ...

  10. 在Visual C++ 6.0中无法使用gets()函数的解决办法

    问题 昨晚遇到一个有意思的问题,明明在Visual Studio 2019运行好好的C语言代码,Copy到Visual C++ 6.0中就无法编译通过了,错误提示信息如下: error C2143: ...