views:

134

answers:

3

In my grails project I'm moving all calculations to java classes.

Here is the link to source code (i've saved it in Google Docs).

Main purpose is to format current time into string(in two languages). Examples:

1 day 2 hours 3 seconds
1 день 2 часа 3 секунды

But i have one method:

 private static boolean endsWith(final long num, final long part) {
    if (num / 10 < 1) {
      return num == part;
    } else {
      float val1 = (num - part) / 10;
      float val2 = (float) Math.floor(val1);

      return val1 == val2;
    }
  }

It checks if 'num' ends with 'part'. Examples:

assert endsWith(128, 1) == false
assert endsWith(1, 1) == true
assert endsWith(34, 4) == true

P.S. num - is standard long (java.lang.Long) value and part - is greater than 0 and less or equals than 9 (1..9).

But this code works fine only in groovy classes.

In java class i got those results:

endsWith(7, 7) == true
endsWith(23, 3) == false
endsWith(23, 1) == true

As i can see from gant log - all code are compiled by groovyc.

P.S.2 I'l compile this code with groovyc and javac to compare results. Because if i haven't make any mistake it could be a bug in groovyc. But this is my mistake i hope :)

+4  A: 

You should never compare floating point values with == due to the limited precision.

In fact in this case it doesn't look like you need to go to floating point operation at all. You can use % to get the remainder of a number and get the last few digits this way.

Here are some examples (note the sign with negative dividend)

123 % 10 == 3
4567 % 100 == 67
-9876 % 10 == -6

References

Related questions


String operation alternative

Another option is that if performance isn't terribly important, the easiest solution is probably to just convert to String and use String.endsWith. In this way you also don't have the complication with negative numbers.

System.out.println(String.valueOf(-9876).endsWith(String.valueOf(76)));
// prints "true"
polygenelubricants
See also Java Puzzlers, 3.1. Floating-point arithmetic is inexact; Avoid testing floating-point values for equality; Prefer double to float;
polygenelubricants
+6  A: 

Why are you using floating point arithmetic at all? Why not just:

private static boolean endsWith(final long num, final long part) {
  return (num % 10) == part;
}

? If it needs to work for negative numbers you'll need to take the absolute value before the mod, but otherwise that should be fine.

Jon Skeet
+3  A: 

I'm not sure, but I'm not comfortable with your conversions to float...

Couldn't you just use return(num % 10) == part?

Bill K