Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 14 additions & 13 deletions src/main/java/com/thealgorithms/maths/Prime/MobiusFunction.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,27 +31,28 @@ public static int mobius(int number) {
throw new IllegalArgumentException("Number must be greater than zero.");
}

if (number == 1) {
// return 1 if number passed is less or is 1
return 1;
}

int primeFactorCount = 0;
int remaining = number;

for (int i = 1; i <= number; i++) {
// find prime factors of number
if (number % i == 0 && PrimeCheck.isPrime(i)) {
// check if number is divisible by square of prime factor
if (number % (i * i) == 0) {
// if number is divisible by square of prime factor
/* Divide out every prime factor in turn. Trial division only has to run up to the square
root of the remaining value, and the multiplication is widened to long so that the bound
does not overflow for numbers close to Integer.MAX_VALUE. */
for (int factor = 2; (long) factor * factor <= remaining; factor++) {
if (remaining % factor == 0) {
remaining /= factor;
if (remaining % factor == 0) {
// number is divisible by the square of this prime factor
return 0;
}
/*increment primeFactorCount by 1
if number is not divisible by square of found prime factor*/
primeFactorCount++;
}
}

/* Whatever is left is either 1 or a single prime factor larger than the square root. */
if (remaining > 1) {
primeFactorCount++;
}

return (primeFactorCount % 2 == 0) ? 1 : -1;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

import com.thealgorithms.maths.Prime.MobiusFunction;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;

class MobiusFunctionTest {

Expand Down Expand Up @@ -152,4 +154,15 @@ void testMobiusFunction() {
assertEquals(expectedValue, actualValue);
}
}

/**
* Large inputs whose smallest square divisor test used to overflow, most notably
* {@code Integer.MAX_VALUE}, whose square wraps around to 1 and made every number look like it
* had a squared prime factor.
*/
@ParameterizedTest
@CsvSource({"2147483647, -1", "2147483646, 0", "2147483645, -1", "2147483644, 0", "2147483629, -1", "2147395600, 0", "1073741824, 0", "1073741789, -1", "999999937, -1", "999999999, 0", "2146689000, 0"})
void testMobiusForLargeNumbers(int number, int expected) {
assertEquals(expected, MobiusFunction.mobius(number));
}
}
Loading