On May 27, 11:57 pm, clintonb <cba...@centurytel.netwrote:

Victor said:

Also, consider that *all calculations* should be performed

in *cents* and not in dollars. You should never have to

"round" anything like '1.115'.

The double value that I'm trying to convert to GCSMoney (which is

implemented as cents) was produced by multiplying a dollar amount by

an interest rate to get interest.

double amount = 126.60;

double interestRate = .075;

double interest = amount * interestRate;

int interestAsCents = interest * 100.0 + 0.5;

The debugger says interest = 9.495.

But when I convert it to cents, we see that interest really

wasn't 9.495 since the cents rounds to 949 instead of 950.

Well, the first error in the above: interestRate is NOT .075,

because .075 can't be represented as a double. Since you start

with an incorrect value, obviously, all of the remaining values

will be incorrect as well.

Below is code where I do my calculations as cents. I can

convert amount to cents by multiplying by 100 since I'm

dealing with a dollar amount. But interest rate is not a

dollar amount. I can't convert it to cents.

No, but it has been specified as an exact decimal fraction, so

you must use some representation which preserves its exact

value, and double isn't it.

(The actually depends on what you're using the monetary values

for. But if it's any bookkeeping, the law generally says

exactly how you have to round, and it it almost always specifies

the rules in terms of decimal values.)

In this particular case, I can convert it to an integer by

multiplying by 1000 since it has three decimal places.

For example. More generally, regardless of the number of

decimal places, you can convert by multiplying by a power of

ten.

This is usually handled with some sort of class, which stores

the integral value and the number of digits after the decimal.

The values are determined directly when converting the input.

double amount = 126.60;

double interestRate = .075;

int amountAsCents = amount * 100; // = 12660

int interestRateAsInt = interestRate * 1000; // = 75

int interestTemp = amountAsCents * interestRateAsInt; // = 949500

interestTemp += 500; // round it. = 950000

int interestAsCents = interestTemp / 1000; // undo interestRate

* 10000. = 950

So this works. But what if I have an interest rate that has

more decimal places? For example, 0.1234? Then I would have

to convert it to an int by multiplying by 10000 and later

divide by 10000.

Given something like:

class Decimal

{

// ...

long long value ;

int scalingFactor ;

} ;

you multiply by multiplying the value, and adding teh

scalingFactor.

In addition to the usual arithmetic operations, you probably

want some functions to round to a specific position, etc.

In general, if I had a money class that stored money amounts

as cents and I needed a multiplication operator that could

multiply a money type by a double, how would I implement that?

Would I just arbitrarily choose the amount of double precision

like this?:

No. Not arbitrarily, but from the input. If the input is 1.23,

then value is 123, and scalingFactor 2. If it is 0.12345, then

value is 12345, and scalingFactor 5.

Clint

int precision = 3;

double amount = 126.60;

double interestRate = .075;

int amountAsCents = amount * 100; // = 12660

int interestRateAsInt = interestRate * pow( 10.0, precision ); //

= 75

int interestTemp = amountAsCents * interestRateAsInt; // = 949500

interestTemp += 5 * pow(10.0, precision - 1 ); // round it. = 950000

int interestAsCents = interestTemp / pow(10.0, precision); //

undo interestRate * 10000. = 950

Or instead of hardcoding the precision in the code above,

could I detect how many decimal places there are and use that

as my precision?

Exactly. And since the only powers you need are those of 10

(and you can probably restrict those, e.g. by restricting the

scalingFactor to +/- 13, like Cobol does), you can easily put

those in a table. (Don't forget that pow(10.0, precision) will

return a possibly inexact double.)

Better yet, I'm sure that there are packages on the market which

do this already. Use one of them.

--

James Kanze (GABI Software) email:ja*********@gmail.com

Conseils en informatique orientée objet/

Beratung in objektorientierter Datenverarbeitung

9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34