HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavaMinor

Computing integer square roots in Java - follow-up

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
rootsjavafollowsquareintegercomputing

Problem

(See the previous iteration.)

My two previous methods for computing the integer square root of a number \$N\$ ran in the \$\mathcal{O}(\sqrt{N})\$ worst case time. Now I have added a method (intSqrt3) that runs in \$\mathcal{O}(\log \sqrt{N})\$ time:

Main.java:

import java.util.Random;
import java.util.function.Function;

public class Main {

    public static long intSqrt1(long number) {
        long sqrt = 0L;

        while ((sqrt + 1) * (sqrt + 1)  number) {
                right = middle - 1;
            } else {
                return middle;
            }
        }

        // Correct the binary search "noise". This iterates no more than 3
        // times.
        long ret = middle + 1;

        while (ret * ret > number) {
            --ret;
        }

        return ret;        
    }

    public static long intSqrt4(long number) {
        return (long) Math.sqrt(number);
    }

    private static void profile(Function function, Long number) {
        long result = 0L;
        long startTime = System.nanoTime();

        for (int i = 0; i < ITERATIONS; ++i) {
            result = function.apply(number);
        }

        long endTime = System.nanoTime();

        System.out.printf("Time: %.2f, result: %d.\n", 
                          (endTime - startTime) / 1e6,
                          result);
    }

    private static final int ITERATIONS = 1_000;
    private static final long UPPER_BOUND = 1_000_000_000_000L;

    public static void main(String[] args) {
        long seed = System.nanoTime();
        Random random = new Random(seed);
        long number = Math.abs(random.nextLong()) % UPPER_BOUND;

        System.out.println("Seed = " + seed);
        System.out.println("Number: " + number);

        profile(Main::intSqrt1, number);
        profile(Main::intSqrt2, number);
        profile(Main::intSqrt3, number);
        profile(Main::intSqrt4, number);
    }
}


The performance figures I get looks like this:

Seed = 19608492647714

Num

Solution

When using function parameters, use the primitive types when available:

Function function


is a red-flag, and should be LongUnaryOperator.

Your code will spin in to an infinite loop for 25% of all long values .... anything larger than Long.MAX_VALUE/4 will cause this loop to become infinite:

// Do the exponential search.
    while (4 * sqrt * sqrt <= number) {
        sqrt *= 2;
    }


About that loop.... why do you have a magic number 4....? What does it do?

This code needs more testing... and magic numbers need to be removed.

Code Snippets

Function<Long, Long> function
// Do the exponential search.
    while (4 * sqrt * sqrt <= number) {
        sqrt *= 2;
    }

Context

StackExchange Code Review Q#117039, answer score: 5

Revisions (0)

No revisions yet.