C++ 实数类

这个类我发现我用的地方还不少,所以,我将它重写了。

以前的写法过于沙雕,还用的模板类,还支持小数转换。实际上我整出这个东西,就是为了不使用小数,那么我为什么还要支持小数的转换?

 

这次我的写法,更多地是为了更简单地使用。

 

 

  1 #pragma once
  2 
  3 #include <stdint.h>
  4 #include <numeric>
  5 #include <iostream>
  6 
  7 class Rational
  8 {
  9 public:
 10     Rational() noexcept : _p(0), _q(1) {}
 11     Rational(int64_t p, int64_t q = 1) : _p(p) { SetQ(q); }
 12     ~Rational() {}
 13 
 14 public:
 15     inline int64_t P() const noexcept { return _p; }
 16     inline void SetP(int64_t p) noexcept { _p = p; }
 17 
 18     inline int64_t Q() const noexcept { return _q; }
 19     inline void SetQ(int64_t q) 
 20     { 
 21         if (q == 0)
 22         {
 23             throw std::logic_error("Integer division by zero.");
 24             return;
 25         }
 26         
 27         _q = q; 
 28     }
 29 
 30     inline int64_t Sign() const noexcept { return _p * _q >= 0 ? 1 : -1; }
 31     inline void Simplify() noexcept 
 32     { 
 33         int64_t g = std::gcd(_p, _q); 
 34         _p /= g; _q /= g;
 35 
 36         if (_p < 0 && _q < 0)
 37         {
 38             _p *= -1;
 39             _q *= -1;
 40         }
 41     }
 42 
 43 public:
 44     template<typename T, typename std::enable_if<std::is_integral<T>::value, T>::type* = nullptr>
 45     inline operator T() const noexcept { return _p / _q; }
 46 
 47     template<typename T, typename std::enable_if<std::is_floating_point<T>::value, T>::type* = nullptr>
 48     inline operator T() const noexcept { return _p / (_q * 1.0); }
 49 
 50     inline friend std::ostream& operator<<(std::ostream& o, const Rational& num)
 51     {
 52         o << num.P() << "/" << num.Q();
 53         return o;
 54     }
 55 
 56     //+
 57     template<typename T, typename std::enable_if<std::is_integral<T>::value, T>::type* = nullptr>
 58     inline friend Rational operator+(const Rational& l, T r) noexcept
 59     {
 60         return Rational(l.Q() * r + l.P(), l.Q());
 61     }
 62 
 63     template<typename T, typename std::enable_if<std::is_integral<T>::value, T>::type* = nullptr>
 64     inline friend Rational operator+(T l, const Rational& r) noexcept
 65     {
 66         return Rational(r.Q() * l + r.P(), r.Q());
 67     }
 68     
 69     inline friend Rational operator+(const Rational& l, const Rational& r) noexcept
 70     {
 71         return Rational(l.P() * r.Q() + l.Q() * r.P(), l.Q() * r.Q());
 72     }
 73 
 74     //-
 75     template<typename T, typename std::enable_if<std::is_integral<T>::value, T>::type* = nullptr>
 76     inline friend Rational operator-(const Rational& l, T r) noexcept
 77     {
 78         return Rational(l.P() - l.Q() * r, l.Q());
 79     }
 80 
 81     template<typename T, typename std::enable_if<std::is_integral<T>::value, T>::type* = nullptr>
 82     inline friend Rational operator-(T l, const Rational& r) noexcept
 83     {
 84         return Rational(r.P() - r.Q() * l, r.Q());
 85     }
 86 
 87     inline friend Rational operator-(const Rational& l, const Rational& r) noexcept
 88     {
 89         return Rational(l.P() * r.Q() - l.Q() * r.P(), l.Q() * r.Q());
 90     }
 91 
 92     //*
 93     template<typename T, typename std::enable_if<std::is_integral<T>::value, T>::type* = nullptr>
 94     inline friend Rational operator*(const Rational& l, T r) noexcept
 95     {
 96         return Rational(l.P() * r, l.Q());
 97     }
 98 
 99     template<typename T, typename std::enable_if<std::is_integral<T>::value, T>::type* = nullptr>
100     inline friend Rational operator*(T l, const Rational& r) noexcept
101     {
102         return Rational(r.P() * l, r.Q());
103     }
104 
105     inline friend Rational operator*(const Rational& l, const Rational& r) noexcept
106     {
107         return Rational(l.P() * r.P(), l.Q() * r.Q());
108     }
109 
110     // /
111     template<typename T, typename std::enable_if<std::is_integral<T>::value, T>::type* = nullptr>
112     inline friend Rational operator/(const Rational& l, T r) noexcept
113     {
114         return Rational(l.P(), l.Q() * r);
115     }
116 
117     template<typename T, typename std::enable_if<std::is_integral<T>::value, T>::type* = nullptr>
118     inline friend Rational operator/(T l, const Rational& r) noexcept
119     {
120         return Rational(r.P(), r.Q() * l);
121     }
122 
123     inline friend Rational operator/(const Rational& l, const Rational& r) noexcept
124     {
125         return Rational(l.P() * r.Q(), l.Q() * r.P());
126     }
127 
128     // = 
129     template<typename T, typename std::enable_if<std::is_integral<T>::value, T>::type* = nullptr>
130     inline Rational& operator=(T r) noexcept
131     {
132         _p = r;
133         _q = 1;
134         return *this;
135     }
136 
137     // +=
138     template<typename TL, typename TR,
139         typename std::enable_if<std::is_same<typename std::decay<TL>::type, Rational>::value || std::is_same<typename std::decay<TR>::type, Rational>::value>::type* = nullptr
140     >
141     inline friend TL& operator+=(TL& l, const TR& r) noexcept
142     {
143         l = l + r;
144         return l;
145     }
146 
147     //-=
148     template<typename TL, typename TR,
149         typename std::enable_if<std::is_same<typename std::decay<TL>::type, Rational>::value || std::is_same<typename std::decay<TR>::type, Rational>::value>::type* = nullptr
150     >
151     inline friend TL& operator-=(TL& l, const TR& r) noexcept
152     {
153         l = l - r;
154         return l;
155     }
156 
157     // *=
158     template<typename TL, typename TR,
159         typename std::enable_if<std::is_same<typename std::decay<TL>::type, Rational>::value || std::is_same<typename std::decay<TR>::type, Rational>::value>::type* = nullptr
160     >
161     inline friend TL& operator*=(TL& l, const TR& r) noexcept
162     {
163         l = l * r;
164         return l;
165     }
166 
167     // /=
168     template<typename TL, typename TR,
169         typename std::enable_if<std::is_same<typename std::decay<TL>::type, Rational>::value || std::is_same<typename std::decay<TR>::type, Rational>::value>::type* = nullptr
170     >
171     inline friend TL& operator/=(TL& l, const TR& r) noexcept
172     {
173         l = l / r;
174         return l;
175     }
176 
177     // <
178     template<typename T, typename std::enable_if<std::is_integral<T>::value, T>::type* = nullptr>
179     inline friend bool operator<(const Rational& l, T r) noexcept
180     {
181         return l.P() < (r * l.Q());
182     }
183 
184     template<typename T, typename std::enable_if<std::is_integral<T>::value, T>::type* = nullptr>
185     inline friend bool operator<(T l, const Rational& r) noexcept
186     {
187         return (l * r.Q()) < r.P();
188     }
189 
190     inline friend bool operator<(const Rational& l, const Rational& r) noexcept
191     {
192         return (l.P() * r.Q()) < (r.P() * l.Q());
193     }
194 
195     // ==
196     template<typename T, typename std::enable_if<std::is_integral<T>::value, T>::type* = nullptr>
197     inline friend bool operator==(const Rational& l, T r) noexcept
198     {
199         return l.P() == (r * l.Q());
200     }
201 
202     template<typename T, typename std::enable_if<std::is_integral<T>::value, T>::type* = nullptr>
203     inline friend bool operator==(T l, const Rational& r) noexcept
204     {
205         return (l * r.Q()) == r.P();
206     }
207 
208     inline friend bool operator==(const Rational& l, const Rational& r) noexcept
209     {
210         return (l.P() * r.Q()) == (r.P() * l.Q());
211     }
212 
213     // >
214     template<typename T, typename std::enable_if<std::is_integral<T>::value, T>::type* = nullptr>
215     inline friend bool operator>(const Rational& l, T r) noexcept
216     {
217         return l.P() > (r * l.Q());
218     }
219 
220     template<typename T, typename std::enable_if<std::is_integral<T>::value, T>::type* = nullptr>
221     inline friend bool operator>(T l, const Rational& r) noexcept
222     {
223         return (l * r.Q()) > r.P();
224     }
225 
226     inline friend bool operator>(const Rational& l, const Rational& r) noexcept
227     {
228         return (l.P() * r.Q()) > (r.P() * l.Q());
229     }
230 
231     // <=
232     template<typename TL, typename TR,
233         typename std::enable_if<std::is_same<typename std::decay<TL>::type, Rational>::value || std::is_same<typename std::decay<TR>::type, Rational>::value>::type* = nullptr
234     >
235     inline friend bool operator<=(TL& l, const TR& r) noexcept
236     {
237         return !(l > r);
238     }
239 
240     // >=
241     template<typename TL, typename TR,
242         typename std::enable_if<std::is_same<typename std::decay<TL>::type, Rational>::value || std::is_same<typename std::decay<TR>::type, Rational>::value>::type* = nullptr
243     >
244     inline friend bool operator>=(TL& l, const TR& r) noexcept
245     {
246         return !(l < r);
247     }
248 
249     // !
250     inline bool operator!() const noexcept
251     {
252         return !(P() == 0);
253     }
254 
255     // ~ (Transposition)
256     inline Rational& operator~() noexcept
257     {
258         int64_t tmp_ = std::move(_p);
259         _p = std::move(_q);
260         SetQ(tmp_);
261 
262         return *this;
263     }
264 
265     //abs
266     inline Rational& Abs() noexcept
267     {
268         std::abs(_p); std::abs(_q);
269         return *this;
270     }
271 
272 private:
273     int64_t _p = 0;
274     int64_t _q = 1;
275 };

 

posted on 2018-10-10 19:29  __Even  阅读(646)  评论(0编辑  收藏  举报

导航