PDA

View Full Version : Java: multiply 11 by 17.39




Howiieque
Jun 19, 2009, 01:44 AM
hi. could you explain...

public class test {
public static void main (String [] args)
{
int a=11;
double b=17.39;
double c=a*b;
System.out.println(c);
}
}

here is what i get:
191.29000000000002

why not 191.29
how to make c just 191.29



Catfish_Man
Jun 19, 2009, 02:13 AM
Remember that your math is being done in base 2, and not all numbers that have finite base 10 representations also have finite base 2 representations.

Howiieque
Jun 19, 2009, 03:27 AM
double subtotal, price;
int quantity;
for (...) {
...
subtotal+=price*quantity;
}

thanks. could you give a little more details?
How can I fix it to ensure that the subtotal can get the right answer after the loop?

cqexbesd
Jun 19, 2009, 04:18 AM
thanks. could you give a little more details?
How can I fix it to ensure that the subtotal can get the right answer after the loop?

Wikipedia will be a good place to start to understand how computers do maths. Articles of interest might include http://en.wikipedia.org/wiki/Floating_point and http://en.wikipedia.org/wiki/Arbitrary-precision_arithmetic. Java has classes such as java.math.BigDecimal that could help however...

Chances are you can just display to only 2 decimal places when displaying your value and that will be good enough (e.g. System.out.printf("%0.2f", subTotal)).

If you feel you need to round off after very calculation then you can do it by multiplying by 100, using round (from Math) and dividing by 100 (I am assuming 2 decimal places here). I would guess that just printing out to 2 decimal places will be sufficient for your needs though, and the least work. You should understand how the maths actually work though, by reading the wikipedia article, as one day you might have a requirement that means you need to care - and besides its interesting.

lee1210
Jun 19, 2009, 08:32 AM
http://forums.macrumors.com/showthread.php?p=7793603&highlight=Money#post7793603

this has come up a few times recently. Knowing what's going on with floating point math is important, but if this is dealing with money this is normally fixed point. You can use integers of the appropriate size, then format them for output.

-Lee

ryan
Jun 19, 2009, 09:09 AM
If you're working with money in Java the best thing to do is to use the BigDecimal (http://java.sun.com/j2se/1.5.0/docs/api/java/math/BigDecimal.html) class. Here a quick rewrite of your application using it:


import java.math.BigDecimal;

public class test {
public static void main (String [] args) {
int a = 11;
BigDecimal b = new BigDecimal("17.39");
BigDecimal c = b.multiply(new BigDecimal(a));
System.out.println(c);
}
}


If you do use the BigDecimal you'll want to become familiar with its scaling settings/methods and with the NumberFormat (http://java.sun.com/j2se/1.5.0/docs/api/java/text/NumberFormat.html) class.

tempusfugit
Jun 19, 2009, 09:10 PM
you could always display it as a string and chop off decimal places

lee1210
Jun 19, 2009, 09:41 PM
you could always display it as a string and chop off decimal places

Unless it has to represent it as 1.9999999997, etc.

If floating point can be avoided, do it.

-Lee

Howiieque
Jun 20, 2009, 10:55 AM
thanks all of you and your suggestions and approaches.
it taught me so much about dealing with money in java.

Eraserhead
Jun 20, 2009, 12:23 PM
FWIW this doesn't just apply to Java - but really any computer language ;).

Wowzera
Jun 21, 2009, 01:01 AM
I've made this class to work with these problems using double/float when working with cash and stuff. If you want, here it goes:

(I've translated the code, it was written on other language, if you get a build error or something else, check the syntax).

I uploaded it (zipped, it's a java file) and posted under:

http://kttns.org/yjbl

public class Coins {

private long cents;

public Coins()
{
this(0.0);
}

public Coins(double value)
{
setValue(value);
}

public double getValue()
{
return this.cents / 100.0;
}

public void setValue(double value)
{
if (value >= 0)
this.cents = (long) (value * 100.0 + 0.5);
else
this.cents = (long) (value * 100.0 - 0.5);
}

public boolean areSame(Object anotherObject)
{
if (!(anotherObject instanceof Coins))
return false;
return getValue() == ((Coins)anotherObject).getValue();
}

protected long getCents()
{
return this.cents;
}

public boolean isBiggerValue(Coins any)
{
if (getCents() > any.getCents())
return true;
return false;
}

public boolean isLowerValue(Coins any)
{
if (getCents() < any.getCents())
return true;
return false;
}

public boolean sameValues(Coins any)
{
if (getCents() == any.getCents())
return true;
return false;
}

protected void setCents(long cents)
{
this.cents = cents;
}
}

Eraserhead
Jun 21, 2009, 05:47 AM
I've made this class to work with these problems using double/float when working with cash and stuff.

You need to use the decimal classes as otherwise you can't guarantee accuracy of the numbers involved.

Howiieque
Jun 24, 2009, 11:21 AM
It is kind of you to provide a lot of approaches to solve the problem. I just pick up the *100 then /100 method due to my simple homework. I shall learn to use the other sophisticated methods in the future. Thank you very much.:)Especial for Wowzera providing his own class.

Eraserhead
Jun 24, 2009, 05:37 PM
It is kind of you to provide a lot of approaches to solve the problem. I just pick up the *100 then /100 method due to my simple homework. I shall learn to use the other sophisticated methods in the future. Thank you very much.:)Especial for Wowzera providing his own class.

Yeah, I should be clear I'm talking about code to be used professionally not homework ;).

craig1410
Jun 24, 2009, 05:53 PM
In my experience as a computer consultant and programmer it is most common for currency values to be stored as integer numbers of pence, cents or some other value and then for the display of this value as a floating point number to be handled at the output stage. For example store $123.45 as the integer 12345 and then use a formatting function to add the currency symbol and decimal point when displaying to the screen.

However, more recently I find myself using Java along with BigDecimal etc.

I'd suggest you learn both methods and get comfortable with each along with any other methods suggested by others. The important thing is to avoid using double data types unless you are doing certain types of scientific calculations where absolute accuracy is not important but speed of execution is. BigDecimal is not as fast to work with as double but is accurate.

Craig.