/** @file
* @brief Fixed-point numbers.
*/
/** @mainpage Project 2 - FIxed-Point Numbers
* This program is Project 2 in Exploring C++,
* by Ray Lischner (Apress).
*
* Your task for Project 2 is to implement a simple fixed-point
* number class. The class represents fixed-point numbers using
* an integer type. The number of places after the decimal point
* is a fixed constant, four. For example, represent the number
* 3.1415 as the integer 31415 and 3.14 as 31400. You must overload
* the arithmetic, comparison, and I/O operators to maintain the
* fixed-point fiction.
*
* Source files:
* - @link fixed.hpp fixed.hpp @endlink
* - @link fixed.cpp fixed.cpp @endlink
* - @link test.cpp test.cpp @endlink: test program
* - @link test.hpp test.hpp @endlink: test header (see Exploration 28)
* - @link ioflags.hpp ioflags.hpp @endlink: save and restore I/O stream flags (Exploration 37)
*
* @author Ray Lischner
*/
#ifndef FIXED_HPP_
#define FIXED_HPP_
#include
#include
#include
/** @brief Implement a fixed-point number class.
* Values have @c places places after the decimal point.
* All arithmetic follows the usual rules.
*/
class fixed
{
public:
typedef int value_type; ///< Type of the actual value
static int const places = 4; ///< number of decimal places
static value_type const places10 = 10000; ///< 10places
/// Default constructor initializes to zero.
fixed() : value_(0) {}
/// Construct from separate integer and fractional parts,
/// e.g., initialize to 123.45 with fixed(123, 45). Initialize
/// to 12.07 with fixed(12, 7).
fixed(value_type integer, value_type fraction);
/// Construct from an integer, with no fraction.
fixed(value_type integer);
/// Construct by rounding off a floating point number.
fixed(double value)
: value_(static_cast(value * places10 + (value < 0 ? -0.5 : 0.5)))
{}
/// Convert to a string.
/// @returns a string representation of the value, e.g., "123.04"
std::string as_string() const;
/// Read from a stream.
/// Overwrite this value with the value read from the stream.
/// @param strm the stream to read
/// @returns true for success or false for failure
bool read(std::istream& strm);
/// Convert to long double.
double as_long_double() const { return static_cast(value()) / places10; }
/// Convert to double.
double as_double() const { return static_cast(value()) / places10; }
/// Convert to float
float as_float() const { return static_cast(value()) / places10; }
/// Return just the integer part, rounded off to the nearest integer.
/// If the value lies equidistant between two integers, round even
/// numbers up and odd numbers down (banker's rounding).
value_type round() const;
/// Return the integer part (which is the same as trunc()).
value_type integer() const { return value() / places10; }
/// Return the fractional part, e.g., 3 for 12.03
value_type fraction() const;
/// Addition assignment operator
fixed& operator+=(fixed f);
/// Subtraction assignment operator
fixed& operator-=(fixed f);
/// Multiplication assignment operator
fixed& operator*=(fixed f);
/// Division assignment operator
fixed& operator/=(fixed f);
/// Negate this value.
void negate();
/// Pre-increment
fixed& operator++();
/// Post-increment
fixed operator++(int);
/// Pre-decrement
fixed& operator--();
/// Post-decrement
fixed operator--(int);
/// Return the internal value.
value_type value() const { return value_; }
private:
/// Reduce frac to the range [0, places10) by discarding digits to the right.
value_type reduce(value_type frac);
value_type value_;
};
/// Read a fixed value
std::istream& operator>>(std::istream& strm, fixed& f);
/// Write a fixed value
std::ostream& operator<<(std::ostream& strm, fixed f);
/// Add fixed values
fixed operator+(fixed a, fixed b);
/// Subtract fixed values
fixed operator-(fixed a, fixed b);
/// Multiply fixed values
fixed operator*(fixed a, fixed b);
/// Divide fixed values
fixed operator/(fixed a, fixed b);
/// Negate a fixed value
fixed operator-(fixed a);
/// Compare fixed values for equality by comparing the underlying values.
bool operator==(fixed a, fixed b);
/// Compare fixed values for inequality by comparing the underlying values.
bool operator!=(fixed a, fixed b);
/// Compare fixed values for less-than by comparing the underlying values.
bool operator<(fixed a, fixed b);
/// Compare fixed values for greater-than by comparing the underlying values.
bool operator>(fixed a, fixed b);
/// Compare fixed values for less-than-or-equal by comparing the underlying values.
bool operator<=(fixed a, fixed b);
/// Compare fixed values for greater-than-or-equal by comparing the underlying values.
bool operator>=(fixed a, fixed b);
#endif