C
clintonb
Steve McConnel, in his book "Code Complete", suggests converting money
amounts from double to integer in order to avoid rounding errors
during calculations. So we made a money class where the money amount
is stored as an integer instead of a double. The cents are stored in
the 10's and 1's position of the integer.
For example: $1.23 is stored as the integer 123. The cents portion
is 23, and the rest is the dollar portion.
However we are having trouble initializing this integer amount when
the original double amount contains fractions of a cent (due to some
interest calculations). We want to round any fractional cents up to
the nearest cent. We use a rounding scheme where values greater than
or equal to 5 are rounded up.
Below is our initialization function. Note that we use the type
__int64 so we can hold larger numbers but the same problems happen
with type int also. myCurrencyx100 is of the type __int64.
The code multiplies the double by 100 first, then it rounds to the
nearest 1, then it converts to int.
So if value = 9.495 we want myCurrencyx100 to be initialized to 950.
But the code sets it to 949.
void GCSMoney::init( const double& value )
{
if( value < 0 )
myCurrencyx100 = static_cast<__int64>(100.0 * value - 0.5);
else
myCurrencyx100 = static_cast<__int64>(100.0 * value + 0.5);
}
I experimented with the order of the calculations. I changed it to
round to the nearest hundredth (cent), then multiply by 100, then
convert to int. This will correctly set myCurrencyx100 to 950 when
the double value is 9.495. But when I tried a double value of 1.115,
it rounded it to 1.11 when it should have rounded it to 1.12. However
the first init method worked for 1.115.
void GCSMoney::init( const double& value )
{
if( value < 0 )
myCurrencyx100 = static_cast<__int64>(100.0 * (value -
0.005));
else
myCurrencyx100 = static_cast<__int64>(100.0 * (value +
0.005));
}
So I have two different methods, but neither works with all values.
For each of these methods, I noticed if I recoded the steps as
individual lines of code, the error happens during the step when
converting the double to int.
Is there any commonly accepted practice for handling these types of
errors?
Thanks in advance,
Clint
amounts from double to integer in order to avoid rounding errors
during calculations. So we made a money class where the money amount
is stored as an integer instead of a double. The cents are stored in
the 10's and 1's position of the integer.
For example: $1.23 is stored as the integer 123. The cents portion
is 23, and the rest is the dollar portion.
However we are having trouble initializing this integer amount when
the original double amount contains fractions of a cent (due to some
interest calculations). We want to round any fractional cents up to
the nearest cent. We use a rounding scheme where values greater than
or equal to 5 are rounded up.
Below is our initialization function. Note that we use the type
__int64 so we can hold larger numbers but the same problems happen
with type int also. myCurrencyx100 is of the type __int64.
The code multiplies the double by 100 first, then it rounds to the
nearest 1, then it converts to int.
So if value = 9.495 we want myCurrencyx100 to be initialized to 950.
But the code sets it to 949.
void GCSMoney::init( const double& value )
{
if( value < 0 )
myCurrencyx100 = static_cast<__int64>(100.0 * value - 0.5);
else
myCurrencyx100 = static_cast<__int64>(100.0 * value + 0.5);
}
I experimented with the order of the calculations. I changed it to
round to the nearest hundredth (cent), then multiply by 100, then
convert to int. This will correctly set myCurrencyx100 to 950 when
the double value is 9.495. But when I tried a double value of 1.115,
it rounded it to 1.11 when it should have rounded it to 1.12. However
the first init method worked for 1.115.
void GCSMoney::init( const double& value )
{
if( value < 0 )
myCurrencyx100 = static_cast<__int64>(100.0 * (value -
0.005));
else
myCurrencyx100 = static_cast<__int64>(100.0 * (value +
0.005));
}
So I have two different methods, but neither works with all values.
For each of these methods, I noticed if I recoded the steps as
individual lines of code, the error happens during the step when
converting the double to int.
Is there any commonly accepted practice for handling these types of
errors?
Thanks in advance,
Clint