RosettaCodeData/Task/M-bius-function/C-sharp/m-bius-function.cs

85 lines
3.1 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
namespace MobiusDemo
{
class Program
{
// -----------------------------------------------------------------
// Settings that are identical to the Java version
// -----------------------------------------------------------------
private const int MU_MAX = 1_000_000; // same upper bound
private static int[] MU = null; // will hold the sieve
static void Main(string[] args)
{
Console.WriteLine("First 199 terms of the möbius function are as follows:");
Console.Write(" ");
for (int n = 1; n < 200; n++)
{
Console.Write($"{MobiusFunction(n),2} ");
// linebreak after every 20 numbers exactly like the Java code
if ((n + 1) % 20 == 0)
Console.WriteLine();
}
}
// -----------------------------------------------------------------
// Compute μ(n) using the same sieve algorithm that the Java code
// uses. The first call builds the whole table up to MU_MAX.
// -----------------------------------------------------------------
private static int MobiusFunction(int n)
{
// If the sieve has already been built we can return the answer
// straight away.
if (MU != null)
return MU[n];
// -------------------------------------------------------------
// Build the sieve (once)
// -------------------------------------------------------------
MU = new int[MU_MAX + 1];
// initialise every entry with 1 Java did this explicitly
for (int i = 0; i <= MU_MAX; i++)
MU[i] = 1;
int sqrt = (int)Math.Sqrt(MU_MAX);
// first pass: multiply by -p for each prime factor p,
// and mark multiples of p² as zero.
for (int i = 2; i <= sqrt; i++)
{
if (MU[i] == 1) // i is still “prime”
{
// flip the sign for every multiple of i
for (int j = i; j <= MU_MAX; j += i)
MU[j] *= -i;
// any number that contains i² gets value 0
int i2 = i * i;
for (int j = i2; j <= MU_MAX; j += i2)
MU[j] = 0;
}
}
// second pass: reduce the encoded values to the final μ(n)
for (int i = 2; i <= MU_MAX; i++)
{
if (MU[i] == i) // only +i => μ = +1
MU[i] = 1;
else if (MU[i] == -i) // only -i => μ = -1
MU[i] = -1;
else if (MU[i] < 0) // product of an odd number of distinct primes
MU[i] = 1;
else if (MU[i] > 0) // product of an even number of distinct primes
MU[i] = -1;
// note: MU[i] == 0 stays 0 (square factor present)
}
return MU[n];
}
}
}