从Groovy转移到Java

4
在我的grails项目中,我正在将所有的计算移到Java类中。

这是源代码的链接(我已将其保存在Google文档中)。

主要目的是将当前时间格式化为字符串(使用两种语言)。例如:
1 day 2 hours 3 seconds
1 день 2 часа 3 секунды

但是我有一个方法:

 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;
    }
  }

它检查'num'是否以'part'结尾。 示例:

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

P.S. num是标准长整型(java.lang.Long)值,部分大于0且小于等于9(1..9)。

但是此代码仅在groovy类中正常工作。

java类中,我得到了这些结果:

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

我可以从甘特图日志中看到 - 所有的代码都是由groovyc编译的。
P.S.2 我会使用groovyc和javac编译此代码以比较结果。因为如果我没有犯任何错误,那么可能是groovyc的一个bug。但我希望这是我的错误 :)

我完全忘记了'%'运算符...而这个人几个月前刚实现了线性同余生成器...难以置信...谢谢大家! - Oleksandr
出于好奇,为什么从Groovy转向Java,是因为性能吗? - Dónal
没错,@Don,你说得对。Groovy根本没有原始值 - 它会自动将double装箱成Double,long装箱成Long等等。因此,由于类型的装箱和拆箱,你会在性能上损失一些东西。 - Oleksandr
3个回答

8
为什么要使用浮点运算?而不是直接使用以下方式:
private static boolean endsWith(final long num, final long part) {
  return (num % 10) == part;
}

如果需要对负数进行取模运算,您需要在取模之前取绝对值,但是其他情况下应该没问题。


6

由于浮点数的精度有限,您不应使用==来比较浮点值。

实际上,在这种情况下,似乎根本不需要进行浮点运算。您可以使用%获取数字的余数,并以此方式获取最后几个数字。

以下是一些示例(请注意负被除数的符号)

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

参考文献

相关问题


String操作替代方案

另一个选择是,如果性能不是非常重要,最简单的解决方案可能是将其转换为String并使用String.endsWith。这样做也没有负数的复杂性。

System.out.println(String.valueOf(-9876).endsWith(String.valueOf(76)));
// prints "true"

1
请参阅《Java Puzzlers》第3.1节。浮点数运算是不精确的,请避免对浮点数进行相等性测试;优先使用double而非float。 - polygenelubricants

3

我不确定,但是我对你转换为浮点数的方式感到不舒服...

你能不能只使用 return(num % 10) == part呢?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接