00001 #include <cassert>
00002 #include <cstdlib>
00003 #include <iomanip>
00004 #include <istream>
00005 #include <locale>
00006 #include <ostream>
00007 #include <sstream>
00008 #include <sstream>
00009 #include <stdexcept>
00010 #include <string>
00011
00012 #include "fixed.hpp"
00013 #include "ioflags.hpp"
00014
00015
00016 fixed::fixed(value_type integer, value_type fraction)
00017 {
00018 if (fraction < 0)
00019 throw std::invalid_argument("negative fraction not allowed");
00020 fraction = reduce(fraction);
00021 if (integer < 0)
00022 value_ = integer * places10 - fraction;
00023 else
00024 value_ = integer * places10 + fraction;
00025 }
00026
00027
00028 fixed::fixed(value_type integer)
00029 : value_(integer * places10)
00030 {}
00031
00032
00033 fixed::value_type fixed::fraction()
00034 const
00035 {
00036 return std::abs(value()) % places10;
00037 }
00038
00048 fixed::value_type fixed::reduce(value_type frac)
00049 {
00050
00051 value_type f(frac);
00052 while (f >= places10*10 and f % 10 == 0)
00053 {
00054 f /= 10;
00055 }
00056
00057 if (f >= places10*10)
00058 {
00059 int x(0);
00060
00061
00062
00063 while (f >= places10)
00064 {
00065 x = f % 10;
00066 f /= 10;
00067 }
00068
00069 if (x >= 5)
00070 ++f;
00071 return f;
00072 }
00073
00074
00075 else if (f >= places10)
00076 {
00077
00078
00079 int x(f % 10);
00080 f /= 10;
00081 assert(f < places10);
00082 if (x == 5)
00083 {
00084
00085 if (f % 2 != 0)
00086 ++f;
00087 return f;
00088 }
00089 else if (x < 5)
00090 {
00091
00092 return f;
00093 }
00094 else
00095 {
00096
00097 return f + 1;
00098 }
00099 }
00100
00101 assert(frac < places10);
00102 return frac;
00103 }
00104
00105
00106 fixed::value_type fixed::round()
00107 const
00108 {
00109 const value_type frac(fraction());
00110 int adjust(value() < 0 ? -1 : +1);
00111 if (frac > places10/2)
00112 return integer()+adjust;
00113 else if (frac < places10/2)
00114 return integer();
00115 else if (integer() % 2 == 0)
00116 return integer();
00117 else
00118 return integer()+adjust;
00119 }
00120
00121
00122 std::string fixed::as_string()
00123 const
00124 {
00125 std::ostringstream out;
00126 out << integer() << '.'
00127 << std::setfill('0') << std::setw(places) << fraction();
00128 return out.str();
00129 }
00130
00131 fixed& fixed::operator+=(fixed f)
00132 {
00133 value_ += f.value();
00134 return *this;
00135 }
00136
00137 fixed& fixed::operator-=(fixed f)
00138 {
00139 value_ -= f.value();
00140 return *this;
00141 }
00142
00143 fixed& fixed::operator*=(fixed f)
00144 {
00145 value_ = (value_ * f.value()) / places10;
00146 return *this;
00147 }
00148
00149 fixed& fixed::operator/=(fixed f)
00150 {
00151 value_ = (value_ * places10) / f.value();
00152 return *this;
00153 }
00154
00155 void fixed::negate()
00156 {
00157 value_ = -value_;
00158 }
00159
00160 fixed& fixed::operator++()
00161 {
00162 value_ += places10;
00163 return *this;
00164 }
00165
00166 fixed fixed::operator++(int)
00167 {
00168 fixed result(*this);
00169 ++*this;
00170 return result;
00171 }
00172
00173 fixed& fixed::operator--()
00174 {
00175 value_ -= places10;
00176 return *this;
00177 }
00178
00179 fixed fixed::operator--(int)
00180 {
00181 fixed result(*this);
00182 --*this;
00183 return result;
00184 }
00185
00186 fixed operator-(fixed a)
00187 {
00188 a.negate();
00189 return a;
00190 }
00191
00192 bool fixed::read(std::istream& strm)
00193 {
00194 ioflags flags(strm);
00195
00196 value_type integer;
00197 char decimal;
00198 if (not (strm >> integer))
00199 return false;
00200 strm.unsetf(std::ios_base::skipws);
00201 if (not (strm >> decimal) or decimal != '.')
00202 {
00203
00204
00205
00206 strm.unget();
00207 strm.clear(strm.rdstate() & ~strm.failbit);
00208 value_ = integer * places10;
00209 return true;
00210 }
00211 else
00212 {
00213 value_type fraction(0);
00214 char c;
00215 int p(0);
00216
00217 for (;
00218 p != places+1 and strm >> c and std::isdigit(c, strm.getloc());
00219 ++p)
00220 {
00221 fraction = fraction * 10 + (c - '0');
00222 }
00223
00224 for (; p < places; ++p)
00225 fraction = fraction * 10;
00226
00227
00228 while (strm and std::isdigit(c, strm.getloc()))
00229 strm >> c;
00230
00231
00232 strm.unget();
00233
00234
00235 strm.clear(strm.rdstate() & ~strm.failbit);
00236 fraction = reduce(fraction);
00237 if (integer < 0)
00238 value_ = integer * places10 - fraction;
00239 else
00240 value_ = integer * places10 + fraction;
00241 }
00242 return true;
00243 }
00244
00245 std::istream& operator>>(std::istream& strm, fixed& f)
00246 {
00247 if (not f.read(strm))
00248 strm.setstate(strm.failbit);
00249 return strm;
00250 }
00251
00252 std::ostream& operator<<(std::ostream& strm, fixed f)
00253 {
00254 strm << f.as_string();
00255 return strm;
00256 }
00257
00258 fixed operator+(fixed a, fixed b)
00259 {
00260 a += b;
00261 return a;
00262 }
00263
00264 fixed operator-(fixed a, fixed b)
00265 {
00266 a -= b;
00267 return a;
00268 }
00269
00270 fixed operator*(fixed a, fixed b)
00271 {
00272 a *= b;
00273 return a;
00274 }
00275
00276 fixed operator/(fixed a, fixed b)
00277 {
00278 a /= b;
00279 return a;
00280 }
00281
00282 bool operator==(fixed a, fixed b)
00283 {
00284 return a.value() == b.value();
00285 }
00286
00287 bool operator!=(fixed a, fixed b)
00288 {
00289 return not (a == b);
00290 }
00291
00292 bool operator<(fixed a, fixed b)
00293 {
00294 return a.value() < b.value();
00295 }
00296
00297 bool operator>(fixed a, fixed b)
00298 {
00299 return b < a;
00300 }
00301
00302 bool operator<=(fixed a, fixed b)
00303 {
00304 return not (b < a);
00305 }
00306
00307 bool operator>=(fixed a, fixed b)
00308 {
00309 return not (a < b);
00310 }