キャストを使用すると、床や円形を使用するよりも高速です。キャストはHotSpotコンパイラによってより高度に最適化されていると思います。
public class Main {
public static final int ITERS = 1000 * 1000;
public static void main(String... args) {
for (int i = 0; i < 3; i++) {
perfRoundTo3();
perfCastRoundTo3();
}
}
private static double perfRoundTo3() {
double sum = 0.0;
long start = 0;
for (int i = -20000; i < ITERS; i++) {
if (i == 0) start = System.nanoTime();
sum += roundTo3(i * 1e-4);
}
long time = System.nanoTime() - start;
System.out.printf("Took %,d ns per round%n", time / ITERS);
return sum;
}
private static double perfCastRoundTo3() {
double sum = 0.0;
long start = 0;
for (int i = -20000; i < ITERS; i++) {
if (i == 0) start = System.nanoTime();
sum += castRoundTo3(i * 1e-4);
}
long time = System.nanoTime() - start;
System.out.printf("Took %,d ns per cast round%n", time / ITERS);
return sum;
}
public static double roundTo3(double d) {
return Math.round(d * 1000 + 0.5) / 1000.0;
}
public static double castRoundTo3(double d) {
return (long) (d * 1000 + 0.5) / 1000.0;
}
}
プリント
Took 22 ns per round
Took 9 ns per cast round
Took 23 ns per round
Took 6 ns per cast round
Took 20 ns per round
Took 6 ns per cast round
注:Java 7の時点では、floor(x + 0.5)とround(x)は、この問題とまったく同じことをしません。Math.round(0.49999999999999994)が1を返すのはなぜですか
これにより、表現エラー内に正しく丸められます。つまり、結果は正確ではありませんが、たとえば0.001は正確に表されませんが、toString()を使用すると、これが修正されます。BigDecimalに変換するか、算術演算を実行した場合にのみ、この表現エラーが表示されます。