How to know a double has significant decimal part or not

Dear members,

I would like to know if a number stored on a double value is really a double or just an integer value.

long iSum = Math.round(sum);// sum is double type

double diff = sum - iSum;

assert diff == 0.0:"The ammount should not be a decimal value";

This is valid under floating ploint arithmetic?

Is there any better and simpler approach?

Thank in advance,

David

[582 byte] By [David_Leala] at [2007-10-3 5:23:57]
# 1

> This is valid under floating ploint arithmetic?

No:double sum = 0.0d;

for(int i = 0; i < 10; i++) {

sum += 0.1d;

}

long iSum = Math.round(sum);

double diff = sum - iSum;

System.out.println("sum = "+sum);

System.out.println("iSum = "+iSum);

System.out.println("diff = "+diff);

> Is there any better and simpler approach?

>

> Thank in advance,

>

> David

For precise calculations use the BigDecimal class:

http://java.sun.com/j2se/1.4.2/docs/api/java/math/BigDecimal.html

When constructing BigDecimal values, be sure to use the constructor which takes a String instead of a double; otherwise you'll have the same round-of errors.

prometheuzza at 2007-7-14 23:31:04 > top of Java-index,Other Topics,Algorithms...
# 2

Thanks for the replay prometheuzz,

So it is not the right way, I have implemented your idea in the following way:

String s1 = String.valueOf(amount); // amount is Double

String s2 = String.valueOf(Math.round(amount.doubleValue()));

BigDecimal num1 = new BigDecimal(s1);

BigDecimal num2 = new BigDecimal(s2);

if (num1.compareTo(num2) != 0) {

assert true: "It is a decimal value and it has to be an integer";

}

Is right way to do this?

Thanks,

David

P.S.: With this check I want that doesn't file for case: 12.0, but files for 12.001.

Curiositity:

For

new Double(12.0000000000000001d) it doesn't file

but

new Double(12.000000000000001d)

if fails (it has one zero less), probably because the precision machine?

David_Leala at 2007-7-14 23:31:04 > top of Java-index,Other Topics,Algorithms...
# 3

You still have round-of errors because 'amount' is still a double.

Try something like this:

BigDecimal sum = new BigDecimal("0.0");

final BigDecimal ONE = new BigDecimal("1.0");

for(int i = 0; i < 10; i++) {

sum = sum.add(new BigDecimal("0.1"));

}

System.out.println("sum == 1 ? "+sum.equals(ONE));

prometheuzza at 2007-7-14 23:31:04 > top of Java-index,Other Topics,Algorithms...
# 4

Testing for equality with floating point numbers when one side or other has been calculated is dangerous because of the buildup of errors. The standard approach I use is that taken by APL which is to use a comparison tollerance. I use a comparator along the lines of that in the example below.

public class Fred211

{

static class FPComparator

{

public FPComparator(double comparisonTollerance)

{

comparisonTollerance_ = Math.abs(comparisonTollerance);

}

public boolean equals(double left, double right)

{

return ((left + comparisonTollerance_) > right) && ((left - comparisonTollerance_) < right);

}

private final double comparisonTollerance_;

}

public static void main(String[] args) throws Exception

{

FPComparator comparator = new FPComparator(1.0e-6);

for (double x = 0.0; ! comparator.equals(x, 10.0); x += 1.0/3)

{

System.out.println(x);

}

}

}

Of couse, if one makes the tollerance too small then one still has problems.

sabre150a at 2007-7-14 23:31:04 > top of Java-index,Other Topics,Algorithms...
# 5

It seems silly to use BigDecimal when your original number is just a double.

Wouldn't something like:

double value = ...

double fraction = value % 1; // this might have to be Math.abs(...)

if (fraction == 0) {

// value is integer

}

However, some people have pointed out that sometimes you'll get numbers like 9.99999999999999967, which probably is really 10, but calculations have introduced precision errors.

So taking from this logic, your fraction would be 0.99999999999999967.

Now you want to know either how far away from 0 or 1 your fraction is, because on the other hand you might have gotten 10.00000000000000001. So you will compare:

if (1 - fraction < threshold) {

// integer

}

else if (fraction < threshold) {

// integer

}

else {

// not integer

}

rkippena at 2007-7-14 23:31:04 > top of Java-index,Other Topics,Algorithms...
# 6

I think in this method, because i need the same:

private boolean isInteger(double n) {

boolean b = false;

int temp = (int)n;

if(n-temp == 0) {//Example: 11.00 - 11 = 0.00

b = true;

}

return b;

}

FRSSa at 2007-7-14 23:31:04 > top of Java-index,Other Topics,Algorithms...
# 7
> I think in this method, because i need the> same:>Congratulations on posting the same solution the original poster did when he posed his question on finding a better approach.The congratulations was sarcastic in case you didn't get it.
rkippena at 2007-7-14 23:31:04 > top of Java-index,Other Topics,Algorithms...