RWDecimal<T> RWDecimalBase
#include <rw/money/decimal.h> /* For RWDecimal<T> */ #include <rw/money/mp2int.h> /* For RWMP2Int */ RWDecimal<RWMP2Int> x = "0.01"; cout << "one dollar: " << 100*x << endl;
The following header files are available for backward compatibility:
#include <rw/dec52.h> /* RWDecimal52 */ #include <rw/dec64.h> /* RWDecimal64 */ #include <rw/dec96.h> /* RWDecimal96 */
com.roguewave.money.currency.v1_0.BigDecimalValue
RWDecimals are exact representations of decimal fractions. They behave very similarly to the built-in floating point types, float and double. However, because the built-in types use base 2, they cannot store decimal fractions exactly, resulting in rounding errors and a loss of precision. Since the RWDecimal<T> classes use base 10, they can do decimal math exactly.
RWDecimal<T> is templatized. Three short type names are provided: RWDecimal<RWMP1Int>, RWDecimal<RWMP2Int>, and RWDecimal<RWMP3Int>. Each type provides a different amount of precision, as described below in the "Limits" section. The trade-off is simple: the more precision, the slower the class.
You may also write your own RWDecimal<T> class. Throughout this section, when we refer to the RWDecimal<T> class, you can assume that it applies to any of the three provided classes, or to one you have defined.
#include <iostream.h> #include <rw/money/decimal.h> #include <rw/money/mp2int.h> main(){ RWDecimal<RWMP2Int> penny = "0.01"; RWDecimal<RWMP2Int> bank = 0; for(int i=100; i--;) bank+=penny; // deposit 100 pennies bank -= 1; // withdraw a buck cout << (bank==0 ? "broke!" : "whew! still solvent") << endl; return 0; }
Class RWDecimal<T> provides three static member functions that can be used to define the limits on an RWDecimal<T> object. These functions return the precision, maximum value, and minimum value of a number:
int RWDecimal<T>::maxDigits() // indicates precision RWDecimal<T> RWDecimal<T>::maxValue() // indicates maximum value RWDecimal<T> RWDecimal<T>::minValue() // indicates minimum value
Note that the precision returned by maxDigits() does not usually represent the number of digits in the maximum value of an RWDecimal<T> object. Rather, it indicates the largest number of digits that will always be supported by that object without returning an overflow error. For example, Table 1 indicates that the maximum value for RWDecimal<RWMP2Int> has 19 digits. Notice, however, that larger 19-digit numbers will cause an overflow error because they exceed the maximum value. Therefore, RWDecimal<RWMP2Int>::maxDigits() returns 18, because that is the number of digits that will always be supported without an overflow error.
The following code snippets demonstrate when an overflow condition caused by exceeding a maximum value will occur:
\\ Set max to maximum value: RWDecimal<RWMP1Int>max = RWDecimal<RWMP1Int>::maxValue() \\ Add 1 to max to generate an overflow error: RWDecimal<RWMP1Int>tooBig = max + RWDecimal<RWMP1Int>(1) \\ Set min to minimum value: RWDecimal<RWMP1Int>min = RWDecimal<RWMP1Int>::minValue() \\ Subtract 1 from min to generate an overflow error: RWDecimal<RWMP1Int>tooSmall = min - RWDecimal<RWMP1Int>(1)
Table 1 indicates the minimum and maximum values for RWDecimal<T> when T is replaced by one of the provided multi-precision integer types:
Class | Minimum value | Max Digits |
Maximum value | ||
RWDecimal<RWMP3Int> |
-39614081257132168796771975167 |
28 |
39614081257132168796771975167 | ||
RWDecimal<RWMP2Int> |
-9223372036854775807 |
18 |
9223372036854775807 | ||
RWDecimal<RWMP1Int> |
-9007199254740991 |
15 |
9007199254740991 |
As well as representing a decimal fraction, an RWDecimal<T> can also represent one of several non-numeric values. This concept has several uses, including, for example, representing a null entry from a database or indicating a missing value in data which is to be subjected to a statistical analysis. Money.h++ supports three of non-numeric values: null, missing, and NaN (not a number). The missing and NaN values propagate while null values do not. This means that arithmetic operations performed using a missing or an NaN result in a missing or an NaN value, whereas arithmetic operations performed with a null operand return either a valid number or an NaN. Details are given below.
The special static variables RWDecimal::missing, RWDecimal::null, and RWDecimal::NaN are the prototype missing and null values. To set up a non-numeric RWDecimal<T> use these static variables along with either the copy constructor or assignment operator. To test for a non-numeric value, use these values along with an equality operator. You can use the member function isNumber() to test if an RWDecimal<T> has a numeric value.
For the most part, arithmetic between RWDecimal<T> objects is defined very simply: you get back an exact representation of the result of the operation. However, there are several special cases:
Loss of precision. If the result cannot be exactly represented as an RWDecimal<T> object because it has too many significant digits, the result is set to an approximation of the true result, and the precisionLoss error handler is called with an RWDecimalInexactErr object.
Overflow/underflow. If the magnitude of the result exceeds the range of RWDecimal<T>, then the overflow error handler is called with an RWDecimalOverflowErr object.
Operand of missing: If one of the operands is a missing value, then the result of the arithmetic operation is also a missing value.
Operand of null: If both operands are null, the result is also null. In addition and subtraction, a null value behaves as if it were zero. In multiplication, a null behaves like a one. Dividing by a null value returns the numerator, thus here a null behaves like one. Using a null as the numerator in a division returns an NaN.
RWDecimal();
Constructs an RWDecimal<T> with a value of null.
RWDecimal(const RWDecimal<T>&);
Copy constructor. Constructs an RWDecimal<T> that is a copy of the argument.
RWDecimal(const char *s);
Constructs an RWDecimal<T> from the null-terminated character string s. Since we write numbers using base 10, and the RWDecimal<T> class stores numbers using base 10, the number constructed is an exact representation of the string. If the string cannot be successfully parsed as a number, the RWDecimal<T> is initialized to null. If the number in the string cannot be exactly represented (for example, it has too many significant digits) then the appropriate error handler (either the inexact or overflow handler) is called. The string may contain embedded commas to separate groups of digits and may have a leading dollar sign. Negatives can be indicated with a negative sign or by using parentheses. A technical description of the exact input grammar allowed is given in the "Technical Notes" section of this manual.
RWDecimal(long int x); RWDecimal(int x);
Constructs an RWDecimal<T> with value x. The explicit integer constructors prevent initializations from 0 from being ambiguous. Without the int constructor, the compiler would not know whether to convert 0 to a const char* or a long int.
RWDecimal(long int x, int e); RWDecimal(int x, int e);
Constructs an RWDecimal<T> with value x*10-e, so that e represents the number of digits after the decimal point.
RWDecimal(const RWDecimalPortable&);
Constructs an RWDecimal<T> representation of the argument. This constructor is most often used implicitly to provide type conversion from one RWDecimal<T> type to another using an RWDecimalPortable object as an intermediate representation.
int decimalPlaces() const;
Returns the number of digits to the right of the decimal point.
RWBoolean isNumber()const;
Returns TRUE if self represents a decimal fraction; returns FALSE if self is not a representation of a number: for example, self is a null or missing value.
void restoreFrom (RWvistream&); void restoreFrom(RWFile&);
Restores value of self from a virtual stream or an RWFile. The virtual streams and RWFile classes are provided with Rogue Wave's Tools.h++ class library. These functions require that you link in the Tools.h++ library.
void saveOn (RWvostream&) const; void saveOn(RWFile&) const;
Stores value of self to a virtual stream, or in binary format to an RWFile. The virtual streams and RWFile classes are provided with Rogue Wave's Tools.h++ class library. These functions require that you link in the Tools.h++ library.
RWDecimal<T>& operator=(const RWDecimal<T>&);
Sets the value of self equal to the value of the argument.
RWDecimal<T>& operator+=(const RWDecimal<T>&); RWDecimal<T>& operator-=(const RWDecimal<T>&); RWDecimal<T>& operator*=(const RWDecimal<T>&); RWDecimal<T>& operator/=(const RWDecimal<T>&);
Performs the operation between self and the argument, and then stores the results in self. If the resulting operation causes loss of precision or overflow in the result, the appropriate error handler will be called before the function returns.
RWDecimalPortable operator RWDecimalPortable() const;
Conversion to a portable decimal object. This is most often used implicitly to interface with a facility such as I/O or type conversion.
RWDecimal<T> operator+(const RWDecimal<T>&); RWDecimal<T> operator-(const RWDecimal<T>&);
Returns the result of applying the unary operator.
RWDecimal<T> operator+(const RWDecimal<T>&, const RWDecimal<T>&); RWDecimal<T> operator-(const RWDecimal<T>&, const RWDecimal<T>&); RWDecimal<T> operator*(const RWDecimal<T>&, const RWDecimal<T>&); RWDecimal<T> operator/(const RWDecimal<T>&, const RWDecimal<T>&);
These arithmetic operators have their conventional meanings. If the resulting operation causes loss of precision or overflow in the result, the appropriate error handler will be called before the function returns.
RWBoolean operator<(const RWDecimal<T>&, const RWDecimal<T>&); RWBoolean operator>(const RWDecimal<T>&, const RWDecimal<T>&); RWBoolean operator<=(const RWDecimal<T>&, const RWDecimal<T>&); RWBoolean operator>=(const RWDecimal<T>&, const RWDecimal<T>&);
The relational operators have their conventional meanings. If one (or both) of the operands is null or missing, then the result of the operator is undefined.
RWBoolean operator==(const RWDecimal<T>&, const RWDecimal<T>&); RWBoolean operator!=(const RWDecimal<T>&, const RWDecimal<T>&);
The equality operator returns TRUE if the two operands are exactly the same, and FALSE otherwise. The not equal operator, !=, does the complement.
istream& operator>>(istream&, RWDecimal<T>&);
Reads an RWDecimal<T> from an input stream. Since we write numbers using base 10 and the RWDecimal<T> class stores numbers using base 10, the number constructed is an exact representation of the input. The number may contain embedded commas to separate groups of digits and may have a leading dollar sign. Negatives can be indicated with a negative sign or by using parentheses. A technical description of the exact input grammar allowed is given in the "Technical Notes" section of this manual.
ostream& operator<<(ostream&, const RWDecimal<T>&);
Writes an RWDecimal<T> to an output stream. Output is written in the form -xxx.yyy where the xxx and yyy are integers and only the necessary parts are written. For more elaborate formatting, use an RWDecimalFormat object.
RWDecimal<T> abs (const RWDecimal<T>& x);
Returns the absolute value of x.
RWDecimal<T> pow(const RWDecimal<T>& x, int n);
Returns x raised to the exponent n. This computation is likely to cause a loss of precision (and a corresponding call to the precision error handler) if n is at all large, and x has any decimal places.
RWDecimal<T> round (const RWDecimal<T>& x, int n, RWDecimalBase::RoundingMethod=PLAIN);
Returns x rounded to n decimal places. The method of rounding is controlled by the optional last parameter as shown in the table below. The last three columns indicate the result of rounding three example numbers to one decimal place. Rounding a negative number returns exactly the same result as rounding the corresponding positive number and making the result negative.
Method | Description | 1.25 | 1.35 | 1.251 |
PLAIN |
Rounds away from zero on a tie |
1.3 |
1.4 |
1.3 |
UP |
Always rounds away from zero |
1.3 |
1.4 |
1.3 |
DOWN |
Always rounds toward zero |
1.2 |
1.3 |
1.2 |
TRUNCATE |
Same as DOWN |
1.2 |
1.3 |
1.2 |
BANKERS |
On a tie, round so last digit is even |
1.2 |
1.4 |
1.3 |
long double toDouble (const RWDecimal<T>& x);
Converts the argument to a double precision value close to its true value.
long int toInt(const RWDecimal<T>& x, RWDecimalBase::RoundingMethod=PLAIN);
Converts the argument to an integer. The method of rounding is controlled by the optional last parameter as described in detail above in the description of the global function round.
RWCString toString(const RWDecimal<T>&);
Converts an RWDecimal<T> to a string. The string produced by this function has the form -xxx.yyy where the xxx and yyy are integers to the left and right of the decimal. Digits only appear if necessary. For more elaborate formatting, use an RWDecimalFormat object.
static RWDecimal<T> from(double); static RWDecimal<T> from(long double);
Converts a floating point value to an RWDecimal. Results may be inexact.
static int maxDigits();
Returns the maximum number of digits that an RWDecimal<T> of the indicated type is guaranteed to represent without overflow. In most cases, an RWDecimal<T> can represent some numbers of length actualDigits, where actualDigits=maxDigits() + 1. For example, the maxDigits() value for class RWDecimal<T> is 18, even though the number of digits in the maxValue() for the class is 19.
static RWDecimal<T> maxValue();
Returns the maximum value that can be represented by this class. The maximum value +1 will always generate an overflow error.
static RWDecimal<T> minValue();
Returns the minimum value that can be represented by this class. The minimum value -1 will always generate an overflow error.
static void setInexactHandler (void (*)(const RWDecimalInexactErr<T>&));
Sets the function that is called when an "inexact" error occurs. This type of error most often indicates the use of an arithmetic operation that will cause loss of precision in the result. defaultInexactHandler, the default error handler, prints an error message, but does not throw an exception.
static void setOverflowHandler(void (*) (const RWDecimalOverflowErr<T>&));
Sets the function that is called when an "overflow" error occurs. This type of error most often indicates the use of an arithmetic operation that will cause a result larger than can be stored. defaultOverflowHandler, the default error handler, simply throws the error object as a C++ exception.
RWDecimal<T> missing; RWDecimal<T> NaN; RWDecimal<T> null;
These are the prototype non-numeric values. Use these to set a RWDecimal<T> to a non-numeric value or to test for a specific non-numeric value.
©Copyright 1999, Rogue Wave Software, Inc.
Send mail to report errors or comment on the documentation.