开发者

Objective C Math Formula Fail

noob here wants to calculate compound interest on iPhone.

float principal;
float rate;
int compoundPerYear;
int years;
flo开发者_如何学JAVAat amount;

formula should be: amount = principal*(1+rate/compoundPerYear)^(rate*years)

I get slightly incorrect answer with:

amount = principal*pow((1+(rate/compoundPerYear)), (compoundPerYear*years));

I'm testing it with rate of .1, but debugger reports .100000001 .

Am I doing it wrong? Should I use doubles or special class (e.g., NSNumber)?

Thanks for any other ideas!


After further research it seems that the NSDecimalNumber class may be just what I need. Now I just have to figure out how to use this bad boy.


double will get you closer, but you can't represent 1/10 exactly in binary (using IEEE floating point notation, anyway).

If you're really interested, you can look at What Every Computer Scientist Should Know About Floating-Point Arithmetic. Link shamefully stolen from another SO thread.

The quick and dirty explanation is that floating point is stored in binary with bits that represents fractional powers of 2 (1/2, 1/4, 1/8, ...). There is simply no mathematical way to add up these fractions to exactly 1/10, thus 0.1 is not able to be exactly represented in IEEE floating point notation.

double extends the accuracy of the number by giving you more numerals before/after the radix, but it does not change the format of the binary in a way that can compensate for this. You'll just get the extra bit somewhere later down the line, most likely.

See also:

  • Why can’t decimal numbers be represented exactly in binary?
  • What’s wrong with using == to compare floats in Java?

and other similar threads.


Further expansion that I mulled over on the drive home from work: one way you could conceivably handle this is by just representing all of the monetary values in cents (as an int), then converting to a dollars.cents format when displaying the data. This is actually pretty easy, too, since you can take advantage of integer division's truncating when you convert:

int interest, dollars, cents;
interest = 16034; //$160.34, in cents
dollars = value / 100; //The 34 gets truncated: dollars == 160
cents = value % 100; //cents == 34
printf("Interest earned to date: $%d.%d\n", dollars, cents);

I don't know Objective-C, but hopefully this C example makes sense, too. Again, this is just one way to handle it. It would also be improved by having a function that does the string formatting whenever you need to show the data.

You can obviously come up with your own (even better!) way to do it, but maybe this will help get you started. If anyone else has suggestions on this one, I'd like to hear them, too!


Short answer: Never use floating point numbers for money.

The easy way that works across most platforms is to represent money as integer amounts of its smallest unit. The smallest unit is often something like a cent, although often 1/10 or 1/100 of a cent are the real base units.

On many platforms, there are also number types available that can represent fixed-point decimals.

Be sure to get the rounding right. Financial bookkeeping often uses banker's rounding.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜