math help

why does the following occur and how can I get around itdouble value=18.9;double precision=100;double ans = value * precision;my solution is: 1889.99999999998why isn't it 1890 and how can I get 1890?Thank You
[258 byte] By [celfiea] at [2007-10-3 2:57:48]
# 1
http://java.sun.com/features/2001/06/floating-point_arithmetic.pdf
el_doradoa at 2007-7-14 20:47:09 > top of Java-index,Java Essentials,Java Programming...
# 2

> why isn't it 1890

Some numbers that can be represented exactly in base-10 cannot be represented exactly in base-2.

For example, one-tenth in base-10 is 0.1

In base-2, you cannot represent this number exactly. It is a repeating fraction, just like one-third is in base-10.

0.1 = 1/2

0.01 = 1/4

etc.

Try to get those negative powers of 2 to add up to exactly one-tenth. You can't do it.

There are uncountably infinitely many numbers in the range covered by double, but only a finite number of bits with which to represent them. Many of them (uncountably infinitely many) cannot be represented exactly, so an approximation will be used.

> and how can I get 1890?

Use java.text.DecimalFormat to format the output, or use java.math.BigDecimal.

jverda at 2007-7-14 20:47:09 > top of Java-index,Java Essentials,Java Programming...
# 3
thank you but can you give me an example of how i can do arthmetic on decimal numbers in java with out this problem?
celfiea at 2007-7-14 20:47:09 > top of Java-index,Java Essentials,Java Programming...
# 4
> thank you but can you give me an example of how i can> do arthmetic on decimal numbers in java with out this> problem?Use java.text.DecimalFormat to format the output, or use java.math.BigDecimal.
tsitha at 2007-7-14 20:47:09 > top of Java-index,Java Essentials,Java Programming...
# 5

> thank you but can you give me an example of how i can

> do arthmetic on decimal numbers in java with out this

> problem?

Read the API docs for the classes I mentioned, or google for examples with those classes. Give it a shot, and if you can't get it to work like you want, post your code with details about whatever problems you're having.

jverda at 2007-7-14 20:47:09 > top of Java-index,Java Essentials,Java Programming...
# 6

The input and output numerals are based on the base or radix 10 (decimal system).

1 * 10`1 + 8*10`0 + 9*10`-1 = 18.9

But the computer uses for the numerals the binary system base on the base 2.

1*2`4 + 0*2`3 + 0*2`2 +1*2`1 + 0*2`0 + 1*2`-1+1*2`-2+1*2`-3+0*2`-3+......

The problem are the transformations from the decimal to the binary system and reverse. In both cases a limited number of bytes is used. Therefore you get the differences.

Using BigDecimal delivers precise results, because they use a BCD (binary coded decimals) representation.

public static void main(String[] args) {

double factor1 = 18.9;

double factor2 = 100;

double result = factor1 * factor2;

System.out.println(" 18.9 * 100 = " + result);

BigDecimal bdFactor1 = new BigDecimal("18.9");

BigDecimal bdFactor2 = new BigDecimal("100");

System.out.println(" 18.9 * 100 = " + bdFactor1.multiply(bdFactor2));

}

Result:

18.9 * 100 = 1889.9999999999998

18.9 * 100 = 1890.0

D_Daniela at 2007-7-14 20:47:09 > top of Java-index,Java Essentials,Java Programming...
# 7
thank you very much guysi'll mule through this and see what happens
celfiea at 2007-7-14 20:47:09 > top of Java-index,Java Essentials,Java Programming...
# 8

I am doing:

BigDecimal bdfirst = new BigDecimal(first);

BigDecimal bdsecond= new BigDecimal(second);

BigDecimal bdtrunc = bdfirst.multiply(bdsecond);

System.out.println(first+" * "+second+" = "+bdtrunc.toString());

my result is:

747.5 * 0.09 = 67.27499999999999751032486727808645810000598430633544921875

the answer should be 67.275 - why am I getting this imprecise value still?

celfiea at 2007-7-14 20:47:09 > top of Java-index,Java Essentials,Java Programming...
# 9

Because you are creating your BigDecimals from the imprecise doubles. TryBigDecimal bdfirst = new BigDecimal("747.5");

BigDecimal bdsecond= new BigDecimal("0.09");

BigDecimal bdtrunc = bdfirst.multiply(bdsecond);

System.out.println(bdfirst+" * "+bdsecond+" = "+bdtrunc.toString());

sabre150a at 2007-7-14 20:47:09 > top of Java-index,Java Essentials,Java Programming...
# 10

ok here is the problem

System.out.println(bdfirst.toString()+" * "+bdsecond.toString()+" = "+bdfirst.multiply(bdsecond));

747.5 * 0.0899999999999999966693309261245303787291049957275390625 = 67.27499999999999751032486727808645810000598430633544921875

So when i create my big decimal objects and pass the constuctor the double as argument, the real number is stored imprecisely mucking up my calculation. Is the solution to convert my doubles to strings before creating the bigdecimal? i can't possibly store all these values as strings - it would require a overhaul of my whole application. any tips?

celfiea at 2007-7-14 20:47:09 > top of Java-index,Java Essentials,Java Programming...
# 11
woops didn't see sabre150 's answer
celfiea at 2007-7-14 20:47:09 > top of Java-index,Java Essentials,Java Programming...
# 12
> it would require a overhaul> of my whole application. any tips?Use double for all your calculations and DecimalFormat to print out the result. For the most part that is what I do.
sabre150a at 2007-7-14 20:47:09 > top of Java-index,Java Essentials,Java Programming...
# 13
last question i promiseif I take my double and do a new double().toString() will this be effective for all cases or should i just retrieve my values as strings directly from the DB
celfiea at 2007-7-14 20:47:09 > top of Java-index,Java Essentials,Java Programming...
# 14

> last question i promise

>

> if I take my double and do a new double().toString()

> will this be effective for all cases or should i just

> retrieve my values as strings directly from the DB

I don't see what you can hope to achieve with this. It probably won't work because once you place a value in a double the damge is done.

Use double and DecimalFormat.

sabre150a at 2007-7-14 20:47:09 > top of Java-index,Java Essentials,Java Programming...
# 15

> if I take my double and do a new double().toString()

> will this be effective for all cases or should i just

> retrieve my values as strings directly from the DB

Don't use:

double someValue = 5;

String string = new Double(someValue).toString();

Use this instead:

double someValue = 5;

String string = Double.toString(someValue);

Or use a DecimalFormat, as necessary. I don't know much about retrieving the values from the database. But, using the second version above eliminates the unnecessary construction of a Double.

MLRona at 2007-7-21 10:03:35 > top of Java-index,Java Essentials,Java Programming...
# 16
thanks for the help
celfiea at 2007-7-21 10:03:35 > top of Java-index,Java Essentials,Java Programming...
# 17

I'm sorry

just to be clear

If i use a double, then convert it to string to be used with BigDecimal, will I run into this problem or should I only be working with Strings? From what I can tell so far, Double.toString() seems to be giving me accurate numbers so is it correct for me to assume that my real number stored in a double will always be returned to me correctly unless i perform arithmetic on it?

celfiea at 2007-7-21 10:03:35 > top of Java-index,Java Essentials,Java Programming...