The Mertens function M(x) is the count of square-free integers up to x that have an even number of prime factors, minus the count of those that have an odd number.

It is an extension of the Möbius function. Given the Möbius function μ(n), the Mertens function M(x) is the sum of the Möbius numbers from n == 1 through n == x.



Task

 Write a routine (function, procedure, whatever) to find the Mertens number for any positive integer x.
 Use that routine to find and display here, on this page, at least the first 99 terms in a grid layout. (Not just one long line or column of numbers.)
 Use that routine to find and display here, on this page, the number of times the Mertens function sequence is equal to zero in the range M(1) through M(1000).
 Use that routine to find and display here, on this page, the number of times the Mertens function sequence crosses zero in the range M(1) through M(1000). (Crossing defined as this term equal to zero but preceding term not.)


See also

 Wikipedia: Mertens function
 Wikipedia: Möbius function
 OEIS: A002321 - Mertens's function
 OEIS: A028442 - Numbers n such that Mertens's function M(n) is zero
 Numberphile - Mertens Conjecture
 Stackexchange: compute the mertens function

This is not code golf.   The stackexchange link is provided as an algorithm reference, not as a guide.



Related tasks

 Möbius function


 
public class MertensFunction {
 
    public static void main(String[] args) {
        System.out.printf("First 199 terms of the merten function are as follows:%n    ");
        for ( int n = 1 ; n < 200 ; n++ ) {
            System.out.printf("%2d  ", mertenFunction(n));
            if ( (n+1) % 20 == 0 ) {
                System.out.printf("%n");
            }
        }
 
        for ( int exponent = 3 ; exponent<= 8 ; exponent++ ) {
            int zeroCount = 0;
            int zeroCrossingCount = 0;
            int positiveCount = 0;
            int negativeCount = 0;
            int mSum = 0;
            int mMin = Integer.MAX_VALUE;
            int mMinIndex = 0;
            int mMax = Integer.MIN_VALUE;
            int mMaxIndex = 0;
            int nMax = (int) Math.pow(10, exponent);
            for ( int n = 1 ; n <= nMax ; n++ ) {
                int m = mertenFunction(n);
                mSum += m;
                if ( m < mMin ) {
                    mMin = m;
                    mMinIndex = n;
                }
                if ( m > mMax ) {
                    mMax = m;
                    mMaxIndex = n;
                }
                if ( m > 0 ) {
                    positiveCount++;
                }
                if ( m < 0 ) {
                    negativeCount++;
                }
                if ( m == 0 ) {
                    zeroCount++;
                }
                if ( m == 0 && mertenFunction(n - 1) != 0 ) {
                    zeroCrossingCount++;
                }
            }
            System.out.printf("%nFor M(x) with x from 1 to %,d%n", nMax);        
            System.out.printf("The maximum of M(x) is M(%,d) = %,d.%n", mMaxIndex, mMax);
            System.out.printf("The minimum of M(x) is M(%,d) = %,d.%n", mMinIndex, mMin);
            System.out.printf("The sum of M(x) is %,d.%n", mSum);
            System.out.printf("The count of positive M(x) is %,d, count of negative M(x) is %,d.%n", positiveCount, negativeCount);
            System.out.printf("M(x) has %,d zeroes in the interval.%n", zeroCount);
            System.out.printf("M(x) has %,d crossings in the interval.%n", zeroCrossingCount);
        }
    }
 
    private static int MU_MAX = 100_000_000;
    private static int[] MU = null;
    private static int[] MERTEN = null;
 
    //  Compute mobius and merten function via sieve
    private static int mertenFunction(int n) {
        if ( MERTEN != null ) {
            return MERTEN[n];
        }
 
        //  Populate array
        MU = new int[MU_MAX+1];
        MERTEN = new int[MU_MAX+1];
        MERTEN[1] = 1;
        int sqrt = (int) Math.sqrt(MU_MAX);
        for ( int i = 0 ; i < MU_MAX ; i++ ) {
            MU[i] = 1;
        }
 
        for ( int i = 2 ; i <= sqrt ; i++ ) {
            if ( MU[i] == 1 ) {
                //  for each factor found, swap + and -
                for ( int j = i ; j <= MU_MAX ; j += i ) {
                    MU[j] *= -i;
                }
                //  square factor = 0
                for ( int j = i*i ; j <= MU_MAX ; j += i*i ) {
                    MU[j] = 0;
                }
            }
        }
 
        int sum = 1;
        for ( int i = 2 ; i <= MU_MAX ; i++ ) {
            if ( MU[i] == i ) {
                MU[i] = 1;
            }
            else if ( MU[i] == -i ) {
                MU[i] = -1;
            }
            else if ( MU[i] < 0 ) {
                MU[i] = 1;               
            }
            else if ( MU[i] > 0 ) {
                MU[i] = -1;
            }
            sum += MU[i];
            MERTEN[i] = sum;
        }
        return MERTEN[n];
    }
 
}
 