urgent : double precision problem

This problem is reported on the forum lots of times by lots of people.

consider situation :

if ((2.9 - 1.1) == 1.8)

do something

else

do otherthings;

Its expected to do something on evaluation of condition in if statement .. instead it enters else part.

secondly, if somewhere in the code,

The BigDecimal can solve the problem in most of the situations but even it has some problems.. sometimes we need to format the contents of BigDecimal before displaying them.. formatting solves display problem but the value stored internally is not proper..

e.g.

formatting to 2 decimal places might display 12.35 for 12.349999 but the value stored in the variable is still 12.349999.

Please let me know if anybody has inputs on this.

Thanks in advance,

[841 byte] By [arun_dj] at [2007-9-26 1:30:12]
# 1

What exactly is your problem? FYI there isn't an accurate finite binary representation for numbers like 1.1 or 2.9 or 1.8 just like 1/3 hasn't got an accurate decimal representation - 0.3333333333333333...

Using BigDecimal should solve this as it stores the value in (pseudo-) decimal system.

jsalonen at 2007-6-29 1:27:57 > top of Java-index,Archived Forums,Java Programming...
# 2

> consider situation :

> if ((2.9 - 1.1) == 1.8)

> do something

> else

> do otherthings;

> Its expected to do something on evaluation of

> condition in if statement .. instead it enters else

> part.

Remember that a computer floating point number isn't always (well, it rarely is) equal to the real world one - it is because special implementation of such number, they have limited precision and are usually base 2 (instead of base 10, as human-readable numbers are).

Instead, you should use:

if ( abs( (2.9-1.1) - 1.8) < precision )

do sth;

else

do sthelse;

where precision is e.g. 0.0001

> The BigDecimal can solve the problem in most of the

> situations but even it has some problems.. sometimes

> we need to format the contents of BigDecimal before

> displaying them.. formatting solves display problem

> but the value stored internally is not proper..

> e.g.

> formatting to 2 decimal places might display 12.35 for

> 12.349999 but the value stored in the variable is

> still 12.349999.

See the answer above.

Robert

rthomanek at 2007-6-29 1:27:58 > top of Java-index,Archived Forums,Java Programming...
# 3

Here is some code that may help you and others who are having a problem with double values. I created this class specifically to be used when using percentages. You can use it to round off values, I have yet to complete the code to round up or truncate values. Once you set the value you can then call the roundOff() method specifying how many decimal places you want to round off (i.e. 2 for percentages). You can then retrieve the value as a double or string or int or float.

I hope that you find this useful.

import java.lang.*;

public class MyDouble extends Number {

private double value;

/**

* MyDouble constructor comment.

*/

public MyDouble() {

super();

}

/**

* MyDouble constructor comment.

*/

public MyDouble(double newValue) {

super();

this.setValue(newValue);

}

/**

* Insert the method's description here.

* Creation date: (2001-01-04 1:24:18 PM)

* @return double

*/

public MyDouble(String inputString) {

super();

this.setValue(inputString);

}

/**

* Insert the method's description here.

* Creation date: (2000-12-28 8:08:54 AM)

* @return double

*/

public double doubleValue() {

return (double)this.getValue();

}

/**

* This method will accept a value to use as decimal positions required.

* It uses the exponent function "e", to move the required decimal positions

* over.

* Creation date: (2001-01-03 3:02:26 PM)

*/

public void exponent(int decimalPositions) {

String text = getValue() + "e" + (decimalPositions);

setValue(Double.valueOf(text).doubleValue());

}

/**

* Insert the method's description here.

* Creation date: (2000-12-28 8:08:54 AM)

* @return double

*/

public float floatValue() {

return (float)this.getValue();

}

/**

* Insert the method's description here.

* Creation date: (2000-12-28 8:20:08 AM)

* @return java.lang.Double

*/

public double getValue() {

return value;

}

/**

* Insert the method's description here.

* Creation date: (2000-12-28 8:08:54 AM)

* @return double

*/

public int intValue() {

return (int)this.getValue();

}

/**

* Insert the method's description here.

* Creation date: (2000-12-28 8:08:54 AM)

* @return double

*/

public long longValue() {

return (long)this.getValue();

}

/**

* Counts the number of numbers that are after the decimal position.

* Creation date: (2000-12-29 8:36:10 AM)

* @return int

*/

public int numberOfNumbersAfterDecimalPosition() {

String text = getValue() + "";

int decimalCount = 0;

for (int i = 0; i < text.length(); i++) {

String characterText = text.valueOf(text.charAt(i));

if (characterText.equals(".")) {

decimalCount = text.length() - 1 - i;

}

}

return decimalCount;

}

/**

* Insert the method's description here.

* Creation date: (2000-12-28 8:33:55 AM)

* @return java.lang.Double

*/

public Double returnDouble() {

return new Double(this.getValue());

}

/**

* Insert the method's description here.

* Creation date: (2000-12-28 8:33:55 AM)

* @return java.lang.Double

*/

public Integer returnInteger() {

return new Integer(this.intValue());

}

/**

* Insert the method's description here.

* Creation date: (2000-12-28 8:33:55 AM)

* @return java.lang.Double

*/

public String returnString() {

return ""+getValue();

}

/**

* This method will round off itself to the specified decimal places.

* There is a maximum size of 7 decimal positions,

* if a bigger number is entered unpredictable results will be returned.

*

* Creation date: (2000-12-20 3:35:07 PM)

*/

public void roundOff(int decimalPositions) {

/* Check the number of decimal postions to determine if the user is requesting an

unneeded rounding. */

if (decimalPositions < this.numberOfNumbersAfterDecimalPosition()) {

int size;

int intValue = 0;

int comparisonInt = 0;

String comparisonString;

Integer comparisonValue;

/* Will create an exponent in string format so that the decimal place can moved

over the requested decimal positions to the right and adds one to the

decimal position so that the value after the cut off position can be evaluated

for rounding purposes. */

String text = "";

if (getValue() > 0.001) {

text = getValue() + "e" + (decimalPositions + 1);

} else {

text = "" + getValue();

}

comparisonInt = Double.valueOf(text).intValue();

text = "" + comparisonInt;

// Determine size of string

size = text.length();

/* Checks the value in the last position of string */

comparisonString = text.valueOf(text.charAt(size-1));

// Converts the value to be compared from a string to an Integer

comparisonValue = Integer.valueOf(comparisonString);

// Creates the actual exponent string to be used

if (getValue() > 0.001) {

text = getValue() + "e" + decimalPositions;

} else {

text = "" + getValue();

}

/* Compares to see if the value should be rounded up. The exponent string is

passed to the valueOf method of a Double and then the int value is determined.

if the value is to be rounded up then 1 is added to the int value.

*/

if (comparisonValue.intValue() >= 5) {

intValue = Double.valueOf(text).intValue() + 1;

}

else {

intValue = Double.valueOf(text).intValue();

}

/* Creates an exponent sting so that the decimal positions can be moved over the

specified decimals places to the left. */

text = intValue + "e-" + decimalPositions;

// The double value of the exponent string is stored in value field

setValue(Double.valueOf(text).doubleValue());

}

}

/**

* Insert the method's description here.

* Creation date: (2000-12-20 3:35:35 PM)

* @return double

*/

public double roundUp() {

return 0;

}

/**

* Insert the method's description here.

* Creation date: (2000-12-28 8:20:08 AM)

* @param newValue java.lang.Double

*/

private void setValue(double newValue) {

value = newValue;

}

/**

* Insert the method's description here.

* Creation date: (2001-01-04 1:28:14 PM)

*/

private void setValue(String newValue) {

value = Double.valueOf(newValue).doubleValue();

}

/**

* Insert the method's description here.

* Creation date: (2001-01-03 2:53:55 PM)

* @return double

*/

public double truncate() {

return 0;

}

}

Robert

EsoralTrebor at 2007-6-29 1:27:58 > top of Java-index,Archived Forums,Java Programming...