Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / First Aid / January 2006

Tip: Looking for answers? Try searching our database.

sorry .09 instead of .08

Thread view: 
joshdalrymple2000@yahoo.com - 29 Jan 2006 22:29 GMT
double totalCost = 3.91, amountPaid = 4.00;
int totalChange;

totalChange = (int)((amountPaid - totalCost) * 100);
System.out.println(totalChange);

it keeps saying the answer is 8... can any one help?
James Westby - 29 Jan 2006 22:46 GMT
> double totalCost = 3.91, amountPaid = 4.00;
> int totalChange;
[quoted text clipped - 3 lines]
>
> it keeps saying the answer is 8... can any one help?

Try looking at the output of this instead

    double totalCost = 3.91, amountPaid = 4.00;
        double totalChange;

        totalChange = ((amountPaid - totalCost) * 100);
        System.out.println(totalChange);

You'll see it isn't 9, and the cast to int truncates it to 8, as you
were seeing originally.

The problem is that you can't use floating point arithmetic (doubles) to
do precise arithmetic. If possible then you should try using fixed point
arithmetic. e.g.

    int totalCost = 391, amountPaid = 400;
    int totalChange;

    totalChange = amountPaid - totalCost;
    System.out.println(totalChange);

James
Thomas Hawtin - 29 Jan 2006 23:00 GMT
> The problem is that you can't use floating point arithmetic (doubles) to
> do precise arithmetic. If possible then you should try using fixed point
> arithmetic. e.g.

It's probably better to use BigDecimal in most situations.

Tom Hawtin
Signature

Unemployed English Java programmer
http://jroller.com/page/tackline/

zero - 29 Jan 2006 23:20 GMT
>> The problem is that you can't use floating point arithmetic (doubles)
>> to do precise arithmetic. If possible then you should try using fixed
[quoted text clipped - 3 lines]
>
> Tom Hawtin

BigDecimal will be slower though.  If the values are all currency values,
with only 2 numbers after the decimal point, ints are a good choice.
Tony Morris - 29 Jan 2006 23:39 GMT
> >> The problem is that you can't use floating point arithmetic (doubles)
> >> to do precise arithmetic. If possible then you should try using fixed
[quoted text clipped - 6 lines]
> BigDecimal will be slower though.  If the values are all currency values,
> with only 2 numbers after the decimal point, ints are a good choice.

Are you saying that billionaires don't exist? My dream has been shattered!!
Use a long - 9223 trillion dollars ought to be enough for anybody, right
Bill?

Signature

Tony Morris
http://tmorris.net/

zero - 30 Jan 2006 19:18 GMT
>> BigDecimal will be slower though.  If the values are all currency
>> values, with only 2 numbers after the decimal point, ints are a good
[quoted text clipped - 3 lines]
> shattered!! Use a long - 9223 trillion dollars ought to be enough for
> anybody, right Bill?

Lol yes I was going to put that in my message - beware of over/underflow,
and use long if you need larger amounts - but I left it out 'cause I was
too lazy and wanted to keep the message short
Thomas Hawtin - 30 Jan 2006 00:09 GMT
> BigDecimal will be slower though.  If the values are all currency values,
> with only 2 numbers after the decimal point, ints are a good choice.

They are slower. However, is it going to make your program noticeably
slower. Almost certainly not. Better to keep it safe than prematurely
optimise.

Using ints is full of traps. No good for a billionaire companies,
although longs should do for storage. Operations such as multiplication
become tricky. Without treating it as a type in its own right, you can
easily get into trouble.

Tom Hawtin
Signature

Unemployed English Java programmer
http://jroller.com/page/tackline/

zero - 30 Jan 2006 19:22 GMT
>> BigDecimal will be slower though.  If the values are all currency
>> values, with only 2 numbers after the decimal point, ints are a good
[quoted text clipped - 10 lines]
>
> Tom Hawtin

BigDecimal has its own problems, beside the speed.  If you initialize a
BigDecimal with a double constant, you're in the same boat as using a
normal double when it comes to rounding errors.

I would suggest int or long for financial calculations, and BigDecimal if
you're dealing with more numbers after the decimal point.
Thomas Hawtin - 30 Jan 2006 20:12 GMT
> BigDecimal has its own problems, beside the speed.  If you initialize a
> BigDecimal with a double constant, you're in the same boat as using a
> normal double when it comes to rounding errors.

If you initialise an int or long with a double you'll get the same
rounding errors (plus overflow errors for added fun). So, don't use
doubles for financial calculations.

Tom Hawtin
Signature

Unemployed English Java programmer
http://jroller.com/page/tackline/

zero - 30 Jan 2006 20:17 GMT
Thomas Hawtin <usenet@tackline.plus.com> wrote in news:43de71ad$0$1458
$ed2619ec@ptn-nntp-reader01.plus.net:

> So, don't use
> doubles for financial calculations.

that's really the bottom line isn't it :-)  Use whatever works for you, as
long as it isn't double (or worse, float).
Ernie Wright - 30 Jan 2006 23:31 GMT
>> So, don't use doubles for financial calculations.
>
> that's really the bottom line isn't it :-)  Use whatever works for
> you, as long as it isn't double (or worse, float).

I'd strongly disagree.  The problem is failure to understand roundoff,
not any particular number representation.  You'll eventually get bitten
if you decide that avoiding floating-point primitives is all you need
to do.  Conversely, if you want to do anything more than adding and
subtracting, you'll find the floating-point primitives very hard to
avoid.

- Ernie                                  http://home.comcast.net/~erniew
Fabien Bergeret - 30 Jan 2006 10:36 GMT
> double totalCost = 3.91, amountPaid = 4.00;
> int totalChange;
[quoted text clipped - 3 lines]
>
> it keeps saying the answer is 8... can any one help?

Never ever perform money calculation using floating point.
First solution : use BigDecimal and BigInteger (which are slower, as
mentioned before).
Second solution (used in all our banking applications) : specify the
amounts in "smallest currency unit" (cents for $, pence for pounds), and
associate a "small unit number" with each currency (if you need to
manage several currencies), which specifies the number of small units
needed for GUI.
For instance, for $, calculations are made in cents, and display is done
with amount/100 $  and amount%100 cents (small unit number = 2)
Thomas Hawtin - 30 Jan 2006 16:35 GMT
> For instance, for $, calculations are made in cents, and display is done
> with amount/100 $  and amount%100 cents (small unit number = 2)

That's not going to work for negative quantities.

IIRC, various legal requirements for calculations will also require a
couple more significant figures.

Tom Hawtin
Signature

Unemployed English Java programmer
http://jroller.com/page/tackline/

Ernie Wright - 30 Jan 2006 19:18 GMT
> double totalCost = 3.91, amountPaid = 4.00;
> int totalChange;
[quoted text clipped - 3 lines]
>
> it keeps saying the answer is 8... can any one help?

As has been said, this is due to roundoff error.

If you want to know *why* roundoff error occurs, it helps to know how
primitive floating-point numbers are stored internally.  Skipping over
the details, the numbers in your example are stored with the following
bit patterns (shown in hex):

          s exp mantissa
   3.91   0 400 F47AE147AE148
   4.0    0 401 0000000000000

Notice that 3.91 can't be represented exactly.  The mantissa is a
repeating fraction, with repeating part 47AE1 that's rounded up at the
end to 48.  The internal version of the number is slightly larger than
3.91.

There is no infallible way to deal with this error, since numbers must
always be stored with a finite number of bits.  How you deal with it
depends on what you're trying to do.

Financial programs usually adhere to a set of conventions that ensure
that a calculation is *fair*, in the sense that it's always done in the
same way.  But this isn't always the same as *accurate*.  Credit card
companies and gas stations will always round up, for example.

Storing money amounts in smaller units (e.g. cents or mils instead of
dollars) hides the problem for addition and subtraction, but not for
anything more complicated (compound interest or statistical analysis).

BigDecimal is overkill unless you need more than 15 decimal digits of
precision.  It's also extremely limited.  There's no pow() method, for
example, so no interest calculations.  And the scaling and rounding of
BigDecimals isn't really any easier or less error-prone than the correct
use of primitive floating-point types.

- Ernie                                  http://home.comcast.net/~erniew


Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.