Skip to main content
Revised benchmark and results based on comments by @maaartinus
Source Link
200_success
  • 145.6k
  • 22
  • 191
  • 481
import java.util.Arrays;

public class DivisibilityBenchmark {
    static abstract class DivPredicate {
        private final String name;

        public DivPredicate(String name) {
            this.name = name;
        }

        public abstract boolean isMultiple(int n);
    }

    private static final long MAAARTINUS_TABLE = 0x9249249249240000L;
    // = 0b1001001001001001001001001001001001001001001001000000000000000000L;

    private static final DivPredicate[] SOLUTIONS = new DivPredicate[] {
        new DivPredicate("canonical") {
            public boolean isMultiple(int n) {
                return n % 3 == 0;
            }
        },

        new DivPredicate("200_success") {
            public boolean isMultiple(int n) {
                return n % 3 == 0;
            }
        },

        new DivPredicate("JavaDeveloper") {
            public boolean isMultiple(int n) {
                if(n < 0) n = -n;

                int evenCtr = 0;
                int oddCtr = 0;

                while (n != 0) {
                    if ((n & 1) == 1) { 
                        oddCtr++;
                    } 
                    n = n>>1;
                    if ((n & 1) == 1) {
                        evenCtr++;
                    } 
                    n = n>>1;
                }

                return evenCtr == oddCtr;
            }
        },

        new DivPredicate("Simon André Forsberg") {
            public boolean isMultiple(int n) {
                int sum = 0;
                int abs = Math.abs(n);
                if (abs < 10) {
                    return abs == 3 || abs == 6 || abs == 9 || abs == 0;
                }
                while (n != 0) {
                    sum += n % 10;
                    n = n / 10;
                }
                return isMultiple(sum);
            }
        },

        new DivPredicate("supercat Rev 2") {
            public boolean isMultiple(int n) {
                int q = (n >> 20) + ((n >> 10) & 0x3ff) + (n & 0x3ff);
                return q == ((q * 0x5556) >> 16) * 3;
            }
        },

        new DivPredicate("supercat Rev 4") {
            public boolean isMultiple(int n) {
                if (n < 0) n = -n;
                int q = (int)((n * 0x55555556L) >> 32);
                n = n - q - q - q;
                return n == 0;
            }
        },

        new DivPredicate("maartinus Rev 4") {
            public boolean isMultiple(int x) {
                int diff = Integer.bitCount(x & 0x2AAAAAAA) + Integer.bitCount(x);
                return (MAAARTINUS_TABLE << diff) < 0;
            }
        },

        new DivPredicate("200_success (bis)") {
            public boolean isMultiple(int n) {
                return n % 3 == 0;
            }
        }
    };

    public static boolean[] run(DivPredicate pred, int lower, int upper) {
        boolean[] results = new boolean[upper - lower];
        for (int i = lower; i < upper; i++) {
            results[i - lower] = pred.isMultiple(i);
        }
        return results;
    }

    public static int perf(DivPredicate pred, int lower, int upper) {
        int count = 0;
        for (int i = lower; i < upper; i++) {
            if (pred.isMultiple(i)) {   // Count results to ensure that the
                count++;                // work is not optimized away
            }
        }
        return count;
    }

    public static void main(String[] args) {
        // Warm-up and correctness tests
        boolean[] expected = null;
        for (DivPredicate pred : SOLUTIONS) {
            boolean[] actual = run(pred, -5000, 5000);
            if (expected == null) {
                expected = actual;
            } else if (!Arrays.equals(expected, actual)) {
                System.out.println("Mismatch " + pred.name);
            }
        }

        // Performance measurement
        final int LOWER = -0x00FFFFFF, UPPER = 0x00FFFFFF;
        for (DivPredicate pred : SOLUTIONS) {
            long start = System.currentTimeMillis();
            perf(pred, LOWER, UPPER);
            long finish = System.currentTimeMillis();
            System.out.printf("Time %s: %d ms\n", pred.name, finish - start);
        }
        for (int i = SOLUTIONS.length - 1; i >= 0; i--) {
            DivPredicate pred = SOLUTIONS[i];
            long start = System.currentTimeMillis();
            perf(pred, LOWER, UPPER);
            long finish = System.currentTimeMillis();
            System.out.printf("Time %s: %d ms\n", pred.name, finish - start);
        }
    }
}
  • Mismatch JavaDeveloper
  • Time 200_successcanonical: 6362 ms (← Grossly unfair advantage!)
  • Time JavaDeveloper200_success: 102079 ms (Still unreliable!)
  • Time Simon André ForsbergJavaDeveloper: 1157995 ms
  • Time supercat Rev 2Simon André Forsberg: 1401146 ms
  • Time supercat Rev 42: 136151 ms
  • Time maaartinussupercat Rev 4: 139146 ms
  • Time maartinus Rev 4: 142 ms
  • Time 200_success (bis): 146 ms (← Probably a fair comparison)
  • Time 200_success (bis): 146 ms
  • Time maartinus Rev 4: 140 ms
  • Time supercat Rev 4: 146 ms
  • Time supercat Rev 2: 153 ms
  • Time Simon André Forsberg: 1168 ms
  • Time JavaDeveloper: 1029 ms
  • Time 200_success: 143 ms
  • Time canonical: 144 ms

Discussion

As @maaartinus points out, the first three solutions in this benchmark receive an unfair advantage due to monomorphic inline caching or other JIT optimizations. To illustrate how the benchmark was flawed, I've included the same solution three times (as "canonical", "200_success", and "200_success (bis)"), then executed the tests in reverse order for good measure. I'll take this as a lesson to use a proper benchmarking tool such as Caliper.

Based on the revised measurements, I would draw the conclusion that solutions by @200_success, @supercat, and @maaartinus are nearly identical in performance.

import java.util.Arrays;

public class DivisibilityBenchmark {
    static abstract class DivPredicate {
        private final String name;

        public DivPredicate(String name) {
            this.name = name;
        }

        public abstract boolean isMultiple(int n);
    }

    private static final long MAAARTINUS_TABLE = 0x9249249249240000L;
    // = 0b1001001001001001001001001001001001001001001001000000000000000000L;

    private static final DivPredicate[] SOLUTIONS = new DivPredicate[] {
        new DivPredicate("200_success") {
            public boolean isMultiple(int n) {
                return n % 3 == 0;
            }
        },

        new DivPredicate("JavaDeveloper") {
            public boolean isMultiple(int n) {
                if(n < 0) n = -n;

                int evenCtr = 0;
                int oddCtr = 0;

                while (n != 0) {
                    if ((n & 1) == 1) { 
                        oddCtr++;
                    } 
                    n = n>>1;
                    if ((n & 1) == 1) {
                        evenCtr++;
                    } 
                    n = n>>1;
                }

                return evenCtr == oddCtr;
            }
        },

        new DivPredicate("Simon André Forsberg") {
            public boolean isMultiple(int n) {
                int sum = 0;
                int abs = Math.abs(n);
                if (abs < 10) {
                    return abs == 3 || abs == 6 || abs == 9 || abs == 0;
                }
                while (n != 0) {
                    sum += n % 10;
                    n = n / 10;
                }
                return isMultiple(sum);
            }
        },

        new DivPredicate("supercat Rev 2") {
            public boolean isMultiple(int n) {
                int q = (n >> 20) + ((n >> 10) & 0x3ff) + (n & 0x3ff);
                return q == ((q * 0x5556) >> 16) * 3;
            }
        },

        new DivPredicate("supercat Rev 4") {
            public boolean isMultiple(int n) {
                if (n < 0) n = -n;
                int q = (int)((n * 0x55555556L) >> 32);
                n = n - q - q - q;
                return n == 0;
            }
        },

        new DivPredicate("maartinus Rev 4") {
            public boolean isMultiple(int x) {
                int diff = Integer.bitCount(x & 0x2AAAAAAA) + Integer.bitCount(x);
                return (MAAARTINUS_TABLE << diff) < 0;
            }
        }
    };

    public static boolean[] run(DivPredicate pred, int lower, int upper) {
        boolean[] results = new boolean[upper - lower];
        for (int i = lower; i < upper; i++) {
            results[i - lower] = pred.isMultiple(i);
        }
        return results;
    }

    public static int perf(DivPredicate pred, int lower, int upper) {
        int count = 0;
        for (int i = lower; i < upper; i++) {
            if (pred.isMultiple(i)) {   // Count results to ensure that the
                count++;                // work is not optimized away
            }
        }
        return count;
    }

    public static void main(String[] args) {
        // Warm-up and correctness tests
        boolean[] expected = null;
        for (DivPredicate pred : SOLUTIONS) {
            boolean[] actual = run(pred, -5000, 5000);
            if (expected == null) {
                expected = actual;
            } else if (!Arrays.equals(expected, actual)) {
                System.out.println("Mismatch " + pred.name);
            }
        }

        // Performance measurement
        final int LOWER = -0x00FFFFFF, UPPER = 0x00FFFFFF;
        for (DivPredicate pred : SOLUTIONS) {
            long start = System.currentTimeMillis();
            perf(pred, LOWER, UPPER);
            long finish = System.currentTimeMillis();
            System.out.printf("Time %s: %d ms\n", pred.name, finish - start);
        }
    }
}
  • Mismatch JavaDeveloper
  • Time 200_success: 63 ms
  • Time JavaDeveloper: 1020 ms
  • Time Simon André Forsberg: 1157 ms
  • Time supercat Rev 2: 140 ms
  • Time supercat Rev 4: 136 ms
  • Time maaartinus Rev 4: 139 ms
import java.util.Arrays;

public class DivisibilityBenchmark {
    static abstract class DivPredicate {
        private final String name;

        public DivPredicate(String name) {
            this.name = name;
        }

        public abstract boolean isMultiple(int n);
    }

    private static final long MAAARTINUS_TABLE = 0x9249249249240000L;
    // = 0b1001001001001001001001001001001001001001001001000000000000000000L;

    private static final DivPredicate[] SOLUTIONS = new DivPredicate[] {
        new DivPredicate("canonical") {
            public boolean isMultiple(int n) {
                return n % 3 == 0;
            }
        },

        new DivPredicate("200_success") {
            public boolean isMultiple(int n) {
                return n % 3 == 0;
            }
        },

        new DivPredicate("JavaDeveloper") {
            public boolean isMultiple(int n) {
                if(n < 0) n = -n;

                int evenCtr = 0;
                int oddCtr = 0;

                while (n != 0) {
                    if ((n & 1) == 1) { 
                        oddCtr++;
                    } 
                    n = n>>1;
                    if ((n & 1) == 1) {
                        evenCtr++;
                    } 
                    n = n>>1;
                }

                return evenCtr == oddCtr;
            }
        },

        new DivPredicate("Simon André Forsberg") {
            public boolean isMultiple(int n) {
                int sum = 0;
                int abs = Math.abs(n);
                if (abs < 10) {
                    return abs == 3 || abs == 6 || abs == 9 || abs == 0;
                }
                while (n != 0) {
                    sum += n % 10;
                    n = n / 10;
                }
                return isMultiple(sum);
            }
        },

        new DivPredicate("supercat Rev 2") {
            public boolean isMultiple(int n) {
                int q = (n >> 20) + ((n >> 10) & 0x3ff) + (n & 0x3ff);
                return q == ((q * 0x5556) >> 16) * 3;
            }
        },

        new DivPredicate("supercat Rev 4") {
            public boolean isMultiple(int n) {
                if (n < 0) n = -n;
                int q = (int)((n * 0x55555556L) >> 32);
                n = n - q - q - q;
                return n == 0;
            }
        },

        new DivPredicate("maartinus Rev 4") {
            public boolean isMultiple(int x) {
                int diff = Integer.bitCount(x & 0x2AAAAAAA) + Integer.bitCount(x);
                return (MAAARTINUS_TABLE << diff) < 0;
            }
        },

        new DivPredicate("200_success (bis)") {
            public boolean isMultiple(int n) {
                return n % 3 == 0;
            }
        }
    };

    public static boolean[] run(DivPredicate pred, int lower, int upper) {
        boolean[] results = new boolean[upper - lower];
        for (int i = lower; i < upper; i++) {
            results[i - lower] = pred.isMultiple(i);
        }
        return results;
    }

    public static int perf(DivPredicate pred, int lower, int upper) {
        int count = 0;
        for (int i = lower; i < upper; i++) {
            if (pred.isMultiple(i)) {   // Count results to ensure that the
                count++;                // work is not optimized away
            }
        }
        return count;
    }

    public static void main(String[] args) {
        // Warm-up and correctness tests
        boolean[] expected = null;
        for (DivPredicate pred : SOLUTIONS) {
            boolean[] actual = run(pred, -5000, 5000);
            if (expected == null) {
                expected = actual;
            } else if (!Arrays.equals(expected, actual)) {
                System.out.println("Mismatch " + pred.name);
            }
        }

        // Performance measurement
        final int LOWER = -0x00FFFFFF, UPPER = 0x00FFFFFF;
        for (DivPredicate pred : SOLUTIONS) {
            long start = System.currentTimeMillis();
            perf(pred, LOWER, UPPER);
            long finish = System.currentTimeMillis();
            System.out.printf("Time %s: %d ms\n", pred.name, finish - start);
        }
        for (int i = SOLUTIONS.length - 1; i >= 0; i--) {
            DivPredicate pred = SOLUTIONS[i];
            long start = System.currentTimeMillis();
            perf(pred, LOWER, UPPER);
            long finish = System.currentTimeMillis();
            System.out.printf("Time %s: %d ms\n", pred.name, finish - start);
        }
    }
}
  • Mismatch JavaDeveloper
  • Time canonical: 62 ms (← Grossly unfair advantage!)
  • Time 200_success: 79 ms (Still unreliable!)
  • Time JavaDeveloper: 995 ms
  • Time Simon André Forsberg: 1146 ms
  • Time supercat Rev 2: 151 ms
  • Time supercat Rev 4: 146 ms
  • Time maartinus Rev 4: 142 ms
  • Time 200_success (bis): 146 ms (← Probably a fair comparison)
  • Time 200_success (bis): 146 ms
  • Time maartinus Rev 4: 140 ms
  • Time supercat Rev 4: 146 ms
  • Time supercat Rev 2: 153 ms
  • Time Simon André Forsberg: 1168 ms
  • Time JavaDeveloper: 1029 ms
  • Time 200_success: 143 ms
  • Time canonical: 144 ms

Discussion

As @maaartinus points out, the first three solutions in this benchmark receive an unfair advantage due to monomorphic inline caching or other JIT optimizations. To illustrate how the benchmark was flawed, I've included the same solution three times (as "canonical", "200_success", and "200_success (bis)"), then executed the tests in reverse order for good measure. I'll take this as a lesson to use a proper benchmarking tool such as Caliper.

Based on the revised measurements, I would draw the conclusion that solutions by @200_success, @supercat, and @maaartinus are nearly identical in performance.

Removed array allocation overhead from timing, as suggested by @maaartinus
Source Link
200_success
  • 145.6k
  • 22
  • 191
  • 481
import java.util.Arrays;

public class DivisibilityBenchmark {
    static abstract class DivPredicate {
        private final String name;

        public DivPredicate(String name) {
            this.name = name;
        }

        public abstract boolean isMultiple(int n);
    }

    private static final long MAAARTINUS_TABLE = 0x9249249249240000L;
    // = 0b1001001001001001001001001001001001001001001001000000000000000000L;

    private static final DivPredicate[] SOLUTIONS = new DivPredicate[] {
        new DivPredicate("200_success") {
            public boolean isMultiple(int n) {
                return n % 3 == 0;
            }
        },

        new DivPredicate("JavaDeveloper") {
            public boolean isMultiple(int n) {
                if(n < 0) n = -n;

                int evenCtr = 0;
                int oddCtr = 0;

                while (n != 0) {
                    if ((n & 1) == 1) { 
                        oddCtr++;
                    } 
                    n = n>>1;
                    if ((n & 1) == 1) {
                        evenCtr++;
                    } 
                    n = n>>1;
                }

                return evenCtr == oddCtr;
            }
        },

        new DivPredicate("Simon André Forsberg") {
            public boolean isMultiple(int n) {
                int sum = 0;
                int abs = Math.abs(n);
                if (abs < 10) {
                    return abs == 3 || abs == 6 || abs == 9 || abs == 0;
                }
                while (n != 0) {
                    sum += n % 10;
                    n = n / 10;
                }
                return isMultiple(sum);
            }
        },

        new DivPredicate("supercat Rev 2") {
            public boolean isMultiple(int n) {
                int q = (n >> 20) + ((n >> 10) & 0x3ff) + (n & 0x3ff);
                return q == ((q * 0x5556) >> 16) * 3;
            }
        },

        new DivPredicate("supercat Rev 4") {
            public boolean isMultiple(int n) {
                if (n < 0) n = -n;
                int q = (int)((n * 0x55555556L) >> 32);
                n = n - q - q - q;
                return n == 0;
            }
        },

        new DivPredicate("maartinus Rev 4") {
            public boolean isMultiple(int x) {
                int diff = Integer.bitCount(x & 0x2AAAAAAA) + Integer.bitCount(x);
                return (MAAARTINUS_TABLE << diff) < 0;
            }
        }
    };

    public static boolean[] run(DivPredicate pred, int lower, int upper) {
        boolean[] results = new boolean[upper - lower];
        for (int i = lower; i < upper; i++) {
            results[i - lower] = pred.isMultiple(i);
        }
        return results;
    }

    public static longint perf(DivPredicate pred, int lower, int upper) {
        longint startcount = System.currentTimeMillis();0;
        runfor (pred,int lower,i upper= lower; i < upper; i++); {
        long finish = System if (pred.currentTimeMillisisMultiple(i);) {   // Count results to ensure that the
        return finish - start;     count++;                // work is not optimized away
            }
        }
        return count;
    }

    public static void main(String[] args) {
        // Warm-up and correctness tests
        boolean[] expected = null;
        for (DivPredicate pred : SOLUTIONS) {
            boolean[] actual = run(pred, -5000, 5000);
            if (expected == null) {
                expected = actual;
            } else if (!Arrays.equals(expected, actual)) {
                System.out.println("Mismatch " + pred.name);
            }
        }

        // Performance measurement
        final int LOWER = -0x00FFFFFF, UPPER = 0x00FFFFFF;
        for (DivPredicate pred : SOLUTIONS) {
            final intlong LOWERstart = -0x00FFFFFFSystem.currentTimeMillis();
            perf(pred, LOWER, UPPER);
            long finish = 0x00FFFFFF;System.currentTimeMillis();
            System.out.printf("Time %s: %d ms\n", pred.name, perf(pred,finish LOWER,- UPPER)start);
        }
    }
}
  • Mismatch JavaDeveloper
  • Time 200_success: 8863 ms
  • Time JavaDeveloper: 9891020 ms
  • Time Simon André Forsberg: 11951157 ms
  • Time supercat Rev 2: 171140 ms
  • Time supercat Rev 4: 161136 ms
  • Time maaartinus Rev 4: 165139 ms
import java.util.Arrays;

public class DivisibilityBenchmark {
    static abstract class DivPredicate {
        private final String name;

        public DivPredicate(String name) {
            this.name = name;
        }

        public abstract boolean isMultiple(int n);
    }

    private static final long MAAARTINUS_TABLE = 0x9249249249240000L;
    // = 0b1001001001001001001001001001001001001001001001000000000000000000L;

    private static final DivPredicate[] SOLUTIONS = new DivPredicate[] {
        new DivPredicate("200_success") {
            public boolean isMultiple(int n) {
                return n % 3 == 0;
            }
        },

        new DivPredicate("JavaDeveloper") {
            public boolean isMultiple(int n) {
                if(n < 0) n = -n;

                int evenCtr = 0;
                int oddCtr = 0;

                while (n != 0) {
                    if ((n & 1) == 1) { 
                        oddCtr++;
                    } 
                    n = n>>1;
                    if ((n & 1) == 1) {
                        evenCtr++;
                    } 
                    n = n>>1;
                }

                return evenCtr == oddCtr;
            }
        },

        new DivPredicate("Simon André Forsberg") {
            public boolean isMultiple(int n) {
                int sum = 0;
                int abs = Math.abs(n);
                if (abs < 10) {
                    return abs == 3 || abs == 6 || abs == 9 || abs == 0;
                }
                while (n != 0) {
                    sum += n % 10;
                    n = n / 10;
                }
                return isMultiple(sum);
            }
        },

        new DivPredicate("supercat Rev 2") {
            public boolean isMultiple(int n) {
                int q = (n >> 20) + ((n >> 10) & 0x3ff) + (n & 0x3ff);
                return q == ((q * 0x5556) >> 16) * 3;
            }
        },

        new DivPredicate("supercat Rev 4") {
            public boolean isMultiple(int n) {
                if (n < 0) n = -n;
                int q = (int)((n * 0x55555556L) >> 32);
                n = n - q - q - q;
                return n == 0;
            }
        },

        new DivPredicate("maartinus Rev 4") {
            public boolean isMultiple(int x) {
                int diff = Integer.bitCount(x & 0x2AAAAAAA) + Integer.bitCount(x);
                return (MAAARTINUS_TABLE << diff) < 0;
            }
        }
    };

    public static boolean[] run(DivPredicate pred, int lower, int upper) {
        boolean[] results = new boolean[upper - lower];
        for (int i = lower; i < upper; i++) {
            results[i - lower] = pred.isMultiple(i);
        }
        return results;
    }

    public static long perf(DivPredicate pred, int lower, int upper) {
        long start = System.currentTimeMillis();
        run(pred, lower, upper);
        long finish = System.currentTimeMillis();
        return finish - start;
    }

    public static void main(String[] args) {
        // Warm-up and correctness tests
        boolean[] expected = null;
        for (DivPredicate pred : SOLUTIONS) {
            boolean[] actual = run(pred, -5000, 5000);
            if (expected == null) {
                expected = actual;
            } else if (!Arrays.equals(expected, actual)) {
                System.out.println("Mismatch " + pred.name);
            }
        }

        // Performance measurement
        for (DivPredicate pred : SOLUTIONS) {
            final int LOWER = -0x00FFFFFF, UPPER = 0x00FFFFFF;
            System.out.printf("Time %s: %d ms\n", pred.name, perf(pred, LOWER, UPPER));
        }
    }
}
  • Mismatch JavaDeveloper
  • Time 200_success: 88 ms
  • Time JavaDeveloper: 989 ms
  • Time Simon André Forsberg: 1195 ms
  • Time supercat Rev 2: 171 ms
  • Time supercat Rev 4: 161 ms
  • Time maaartinus Rev 4: 165 ms
import java.util.Arrays;

public class DivisibilityBenchmark {
    static abstract class DivPredicate {
        private final String name;

        public DivPredicate(String name) {
            this.name = name;
        }

        public abstract boolean isMultiple(int n);
    }

    private static final long MAAARTINUS_TABLE = 0x9249249249240000L;
    // = 0b1001001001001001001001001001001001001001001001000000000000000000L;

    private static final DivPredicate[] SOLUTIONS = new DivPredicate[] {
        new DivPredicate("200_success") {
            public boolean isMultiple(int n) {
                return n % 3 == 0;
            }
        },

        new DivPredicate("JavaDeveloper") {
            public boolean isMultiple(int n) {
                if(n < 0) n = -n;

                int evenCtr = 0;
                int oddCtr = 0;

                while (n != 0) {
                    if ((n & 1) == 1) { 
                        oddCtr++;
                    } 
                    n = n>>1;
                    if ((n & 1) == 1) {
                        evenCtr++;
                    } 
                    n = n>>1;
                }

                return evenCtr == oddCtr;
            }
        },

        new DivPredicate("Simon André Forsberg") {
            public boolean isMultiple(int n) {
                int sum = 0;
                int abs = Math.abs(n);
                if (abs < 10) {
                    return abs == 3 || abs == 6 || abs == 9 || abs == 0;
                }
                while (n != 0) {
                    sum += n % 10;
                    n = n / 10;
                }
                return isMultiple(sum);
            }
        },

        new DivPredicate("supercat Rev 2") {
            public boolean isMultiple(int n) {
                int q = (n >> 20) + ((n >> 10) & 0x3ff) + (n & 0x3ff);
                return q == ((q * 0x5556) >> 16) * 3;
            }
        },

        new DivPredicate("supercat Rev 4") {
            public boolean isMultiple(int n) {
                if (n < 0) n = -n;
                int q = (int)((n * 0x55555556L) >> 32);
                n = n - q - q - q;
                return n == 0;
            }
        },

        new DivPredicate("maartinus Rev 4") {
            public boolean isMultiple(int x) {
                int diff = Integer.bitCount(x & 0x2AAAAAAA) + Integer.bitCount(x);
                return (MAAARTINUS_TABLE << diff) < 0;
            }
        }
    };

    public static boolean[] run(DivPredicate pred, int lower, int upper) {
        boolean[] results = new boolean[upper - lower];
        for (int i = lower; i < upper; i++) {
            results[i - lower] = pred.isMultiple(i);
        }
        return results;
    }

    public static int perf(DivPredicate pred, int lower, int upper) {
        int count = 0;
        for (int i = lower; i < upper; i++) {
            if (pred.isMultiple(i)) {   // Count results to ensure that the
                count++;                // work is not optimized away
            }
        }
        return count;
    }

    public static void main(String[] args) {
        // Warm-up and correctness tests
        boolean[] expected = null;
        for (DivPredicate pred : SOLUTIONS) {
            boolean[] actual = run(pred, -5000, 5000);
            if (expected == null) {
                expected = actual;
            } else if (!Arrays.equals(expected, actual)) {
                System.out.println("Mismatch " + pred.name);
            }
        }

        // Performance measurement
        final int LOWER = -0x00FFFFFF, UPPER = 0x00FFFFFF;
        for (DivPredicate pred : SOLUTIONS) {
            long start = System.currentTimeMillis();
            perf(pred, LOWER, UPPER);
            long finish = System.currentTimeMillis();
            System.out.printf("Time %s: %d ms\n", pred.name, finish - start);
        }
    }
}
  • Mismatch JavaDeveloper
  • Time 200_success: 63 ms
  • Time JavaDeveloper: 1020 ms
  • Time Simon André Forsberg: 1157 ms
  • Time supercat Rev 2: 140 ms
  • Time supercat Rev 4: 136 ms
  • Time maaartinus Rev 4: 139 ms
Incorporated revised code from various answers; refactored to make @Simon happy
Source Link
200_success
  • 145.6k
  • 22
  • 191
  • 481
import java.util.Arrays;

public class DivisibilityBenchmark {
    interfacestatic abstract class DivPredicate {
        boolean isMultiple(int n);
 private final String }name;

    private static final DivPredicate solJavaDeveloper = newpublic DivPredicate(String name) {
        public boolean isMultiple(int n) {
       this.name = name;
   if(n < 0) n = -n;}

         public abstract boolean isMultiple(int evenCtr = 0;n);
            int oddCtr = 0;}

         private static final whilelong (nMAAARTINUS_TABLE != 0) {
                if ((n & 1) == 1) { 0x9249249249240000L;
                  // = oddCtr++;0b1001001001001001001001001001001001001001001001000000000000000000L;
                } 
            private static final DivPredicate[] nSOLUTIONS = n>>1;
      new DivPredicate[] {
        ifnew (DivPredicate(n & 1) == 1"200_success") {
                public boolean isMultiple(int n) evenCtr++;{
                } 
             return n % n3 === n>>1;0;
            }
        },

        new DivPredicate("JavaDeveloper") {
  return evenCtr == oddCtr;
       public }boolean isMultiple(int n) {
    };            if(n < 0) n = -n;

    private static final DivPredicate sol200_success = new DivPredicate() {
        public boolean isMultiple(int n) {
   evenCtr = 0;
       return n % 3 == 0;
        }
 int oddCtr = };0;

    private static final DivPredicate solSimon = new DivPredicate     while (n != 0) {
        public boolean isMultiple(int          if ((n & 1) == 1) { 
            int sum = 0;         oddCtr++;
            int abs = Math.abs(     } 
                    n); = n>>1;
                    if (abs(n <& 101) == 1) {
                return abs == 3 || abs == 6 ||evenCtr++;
 abs == 9 || abs               } 
                    n = n>>1;
                }

                return evenCtr == 0;oddCtr;
            }
        },

        new DivPredicate("Simon André Forsberg") {
            public boolean isMultiple(int n) {
                int sum = 0;
                int abs = Math.abs(n);
                if (abs < 10) {
                    return abs == 3 || abs == 6 || abs == 9 || abs == 0;
                }
                while (n != 0) {
                    sum += n % 10;
                    n = n / 10;
                }
                return isMultiple(sum);
            }
            return isMultiple(sum);
        }
    };,

    private static final DivPredicate solSupercat = new DivPredicate("supercat Rev 2") {
            public boolean isMultiple(int n) {
                int q = (n >> 20) + ((n >> 10) & 0x3ff) + (n & 0x3ff);
                return q == ((q * 0x5556) >> 16) * 3;
            }
        };,

    private static final int tablenew =DivPredicate("supercat 0b001001001001001001001001001001001;Rev 4") {
    private static final DivPredicate solMaaartinus = new DivPredicate public boolean isMultiple(int n) {
        public boolean isMultiple      if (n < 0) n = -n;
                int q = (int)((n * 0x55555556L) {>> 32);
            int mask   n = 0x2aaaaaaa;n - q - q - q;
                return n == 0;
            }
        },

        new DivPredicate("maartinus Rev 4") {
            public boolean isMultiple(int x) {
                int diff = Integer.bitCount(nx & mask0x2AAAAAAA) -+ Integer.bitCount(n & ~maskx);
                return (tableMAAARTINUS_TABLE << (diff + 16)) < 0;
            }
        }
    };

    public static boolean[] testrun(DivPredicate pred, int lower, int upper) {
        boolean[] results = new boolean[upper - lower];
        for (int i = lower; i < upper; i++) {
            results[i - lower] = pred.isMultiple(i);
        }
        return results;
    }

    public static long perf(DivPredicate pred, int lower, int upper) {
        long start = System.currentTimeMillis();
        run(pred, lower, upper);
        long finish = System.currentTimeMillis();
        return finish - start;
    }

    public static void main(String[] args) {
        // Warm-up and correctness tests
        boolean[] resultJavaDeveloperexpected = test(solJavaDeveloper, -5000, 5000);null;
        boolean[] result200_success   =for test(sol200_success, DivPredicate pred -5000,: 5000SOLUTIONS);
        boolean[] resultSimon         = test(solSimon,         -5000, 5000);{
        boolean[] resultSupercat    boolean[] actual = testrun(solSupercatpred,      -5000, 5000);
        boolean[] resultMaaartinus    =if test(solMaaartinus,   expected -5000,== 5000null);

      {
  if (!Arrays.equals(result200_success, resultJavaDeveloper)) {
           expected System.out.println("Mismatch= JavaDeveloper");actual;
        }
      } else if (!Arrays.equals(result200_successexpected, resultSimonactual)) {
            System.out.println("Mismatch Simon André Forsberg");
        }
        if (!Arrays.equals(result200_success, resultSupercat)) {
            System.out.println("Mismatch Supercat");
        }
       " if+ (!Arrayspred.equals(result200_success, resultMaaartinus)name) {;
            System.out.println("Mismatch maaartinus");}
        }

        // Performance measurement
        int lower = -0x00FFFFFF, upper = 0x00FFFFFF;
        long start, finish;

        start = System.currentTimeMillis();
        resultJavaDeveloper = test(solJavaDeveloper, lower, upper);
        finish =for System.currentTimeMillis();
       DivPredicate System.out.printf("Timepred JavaDeveloper: %d ms\n", finish - startSOLUTIONS);

        start = System.currentTimeMillis();{
        result200_success = test(sol200_success, lower, upper);
      final int finishLOWER = System.currentTimeMillis();
        System.out.printf("Time 200_success: %d ms\n", finish - start);

        start = System.currentTimeMillis();
        resultSimon = test(solSimon, lower, upper);
        finish = System.currentTimeMillis();
        System.out.printf("Time Simon André Forsberg: %d ms\n"0x00FFFFFF, finish - start);

        start = System.currentTimeMillis();
        result200_successUPPER = test(solSupercat, lower, upper);0x00FFFFFF;
        finish = System.currentTimeMillis();
        System.out.printf("Time Supercat%s: %d ms\n", finish - start);

        start = Systempred.currentTimeMillis();
        result200_success =name, testperf(solMaaartinuspred, lowerLOWER, upperUPPER);
        finish = System.currentTimeMillis();
        System.out.printf("Time maaartinus: %d ms\n", finish - start);}
    }
}

Java(TM) SE Runtime Environment (build 1.7.0_45-b18) on OS X 10.9, Intel Core i7 Arrandale 2-2600 Sandy Bridge 3.664 GHz:

  • Mismatch JavaDeveloper
  • Time JavaDeveloper200_success: 116088 ms
  • Time 200_successJavaDeveloper: 109989 ms
  • Time Simon André Forsberg: 15831195 ms
  • Time Supercatsupercat Rev 2: 260171 ms
  • Time supercat Rev 4: 161 ms
  • Time maaartinus Rev 4: 262165 ms
import java.util.Arrays;

public class DivisibilityBenchmark {
    interface DivPredicate {
        boolean isMultiple(int n);
    }

    private static final DivPredicate solJavaDeveloper = new DivPredicate() {
        public boolean isMultiple(int n) {
            if(n < 0) n = -n;

            int evenCtr = 0;
            int oddCtr = 0;

            while (n != 0) {
                if ((n & 1) == 1) { 
                    oddCtr++;
                } 
                n = n>>1;
                if ((n & 1) == 1) {
                    evenCtr++;
                } 
                n = n>>1;
            }

            return evenCtr == oddCtr;
        }
    };

    private static final DivPredicate sol200_success = new DivPredicate() {
        public boolean isMultiple(int n) {
            return n % 3 == 0;
        }
    };

    private static final DivPredicate solSimon = new DivPredicate() {
        public boolean isMultiple(int n) {
            int sum = 0;
            int abs = Math.abs(n);
            if (abs < 10) {
                return abs == 3 || abs == 6 || abs == 9 || abs == 0;
            }
            while (n != 0) {
                sum += n % 10;
                n = n / 10;
            }
            return isMultiple(sum);
        }
    };

    private static final DivPredicate solSupercat = new DivPredicate() {
        public boolean isMultiple(int n) {
            int q = (n >> 20) + ((n >> 10) & 0x3ff) + (n & 0x3ff);
            return q == ((q * 0x5556) >> 16) * 3;
        }
    };

    private static final int table = 0b001001001001001001001001001001001;
    private static final DivPredicate solMaaartinus = new DivPredicate() {
        public boolean isMultiple(int n) {
            int mask = 0x2aaaaaaa;
            int diff = Integer.bitCount(n & mask) - Integer.bitCount(n & ~mask);
            return (table << (diff + 16)) < 0;
        }
    };

    public static boolean[] test(DivPredicate pred, int lower, int upper) {
        boolean[] results = new boolean[upper - lower];
        for (int i = lower; i < upper; i++) {
            results[i - lower] = pred.isMultiple(i);
        }
        return results;
    }

    public static void main(String[] args) {
        // Warm-up and correctness tests
        boolean[] resultJavaDeveloper = test(solJavaDeveloper, -5000, 5000);
        boolean[] result200_success   = test(sol200_success,   -5000, 5000);
        boolean[] resultSimon         = test(solSimon,         -5000, 5000);
        boolean[] resultSupercat      = test(solSupercat,      -5000, 5000);
        boolean[] resultMaaartinus    = test(solMaaartinus,    -5000, 5000);

        if (!Arrays.equals(result200_success, resultJavaDeveloper)) {
            System.out.println("Mismatch JavaDeveloper");
        }
        if (!Arrays.equals(result200_success, resultSimon)) {
            System.out.println("Mismatch Simon André Forsberg");
        }
        if (!Arrays.equals(result200_success, resultSupercat)) {
            System.out.println("Mismatch Supercat");
        }
        if (!Arrays.equals(result200_success, resultMaaartinus)) {
            System.out.println("Mismatch maaartinus");
        }

        // Performance measurement
        int lower = -0x00FFFFFF, upper = 0x00FFFFFF;
        long start, finish;

        start = System.currentTimeMillis();
        resultJavaDeveloper = test(solJavaDeveloper, lower, upper);
        finish = System.currentTimeMillis();
        System.out.printf("Time JavaDeveloper: %d ms\n", finish - start);

        start = System.currentTimeMillis();
        result200_success = test(sol200_success, lower, upper);
        finish = System.currentTimeMillis();
        System.out.printf("Time 200_success: %d ms\n", finish - start);

        start = System.currentTimeMillis();
        resultSimon = test(solSimon, lower, upper);
        finish = System.currentTimeMillis();
        System.out.printf("Time Simon André Forsberg: %d ms\n", finish - start);

        start = System.currentTimeMillis();
        result200_success = test(solSupercat, lower, upper);
        finish = System.currentTimeMillis();
        System.out.printf("Time Supercat: %d ms\n", finish - start);

        start = System.currentTimeMillis();
        result200_success = test(solMaaartinus, lower, upper);
        finish = System.currentTimeMillis();
        System.out.printf("Time maaartinus: %d ms\n", finish - start);
    }
}

Java(TM) SE Runtime Environment (build 1.7.0_45-b18) on OS X 10.9, Intel Core i7 Arrandale 2.66 GHz:

  • Mismatch JavaDeveloper
  • Time JavaDeveloper: 1160 ms
  • Time 200_success: 109 ms
  • Time Simon André Forsberg: 1583 ms
  • Time Supercat: 260 ms
  • Time maaartinus: 262 ms
import java.util.Arrays;

public class DivisibilityBenchmark {
    static abstract class DivPredicate {
        private final String name;

        public DivPredicate(String name) {
            this.name = name;
        }

        public abstract boolean isMultiple(int n);
    }

    private static final long MAAARTINUS_TABLE = 0x9249249249240000L;
    // = 0b1001001001001001001001001001001001001001001001000000000000000000L;

    private static final DivPredicate[] SOLUTIONS = new DivPredicate[] {
        new DivPredicate("200_success") {
            public boolean isMultiple(int n) {
                return n % 3 == 0;
            }
        },

        new DivPredicate("JavaDeveloper") {
            public boolean isMultiple(int n) {
                if(n < 0) n = -n;

                int evenCtr = 0;
                int oddCtr = 0;

                while (n != 0) {
                    if ((n & 1) == 1) { 
                        oddCtr++;
                    } 
                    n = n>>1;
                    if ((n & 1) == 1) {
                        evenCtr++;
                    } 
                    n = n>>1;
                }

                return evenCtr == oddCtr;
            }
        },

        new DivPredicate("Simon André Forsberg") {
            public boolean isMultiple(int n) {
                int sum = 0;
                int abs = Math.abs(n);
                if (abs < 10) {
                    return abs == 3 || abs == 6 || abs == 9 || abs == 0;
                }
                while (n != 0) {
                    sum += n % 10;
                    n = n / 10;
                }
                return isMultiple(sum);
            }
        },

        new DivPredicate("supercat Rev 2") {
            public boolean isMultiple(int n) {
                int q = (n >> 20) + ((n >> 10) & 0x3ff) + (n & 0x3ff);
                return q == ((q * 0x5556) >> 16) * 3;
            }
        },

        new DivPredicate("supercat Rev 4") {
            public boolean isMultiple(int n) {
                if (n < 0) n = -n;
                int q = (int)((n * 0x55555556L) >> 32);
                n = n - q - q - q;
                return n == 0;
            }
        },

        new DivPredicate("maartinus Rev 4") {
            public boolean isMultiple(int x) {
                int diff = Integer.bitCount(x & 0x2AAAAAAA) + Integer.bitCount(x);
                return (MAAARTINUS_TABLE << diff) < 0;
            }
        }
    };

    public static boolean[] run(DivPredicate pred, int lower, int upper) {
        boolean[] results = new boolean[upper - lower];
        for (int i = lower; i < upper; i++) {
            results[i - lower] = pred.isMultiple(i);
        }
        return results;
    }

    public static long perf(DivPredicate pred, int lower, int upper) {
        long start = System.currentTimeMillis();
        run(pred, lower, upper);
        long finish = System.currentTimeMillis();
        return finish - start;
    }

    public static void main(String[] args) {
        // Warm-up and correctness tests
        boolean[] expected = null;
        for (DivPredicate pred : SOLUTIONS) {
            boolean[] actual = run(pred, -5000, 5000);
            if (expected == null) {
                expected = actual;
            } else if (!Arrays.equals(expected, actual)) {
                System.out.println("Mismatch " + pred.name);
            }
        }

        // Performance measurement
        for (DivPredicate pred : SOLUTIONS) {
            final int LOWER = -0x00FFFFFF, UPPER = 0x00FFFFFF;
            System.out.printf("Time %s: %d ms\n", pred.name, perf(pred, LOWER, UPPER));
        }
    }
}

Java(TM) SE Runtime Environment (build 1.7.0_45-b18) on OS X 10.9, Intel Core i7-2600 Sandy Bridge 3.4 GHz:

  • Mismatch JavaDeveloper
  • Time 200_success: 88 ms
  • Time JavaDeveloper: 989 ms
  • Time Simon André Forsberg: 1195 ms
  • Time supercat Rev 2: 171 ms
  • Time supercat Rev 4: 161 ms
  • Time maaartinus Rev 4: 165 ms
Source Link
200_success
  • 145.6k
  • 22
  • 191
  • 481
Loading
Post Made Community Wiki by 200_success