64 votes

Calculer la médiane en c#

J'ai besoin d'écrire une fonction qui accepte un tableau de décimales et qui trouve la médiane.

Existe-t-il une fonction dans la bibliothèque mathématique de .net ?

5voto

Will Calderwood Points 957

Voici une version générique de la réponse de Jason

    /// <summary>
    /// Gets the median value from an array
    /// </summary>
    /// <typeparam name="T">The array type</typeparam>
    /// <param name="sourceArray">The source array</param>
    /// <param name="cloneArray">If it doesn't matter if the source array is sorted, you can pass false to improve performance</param>
    /// <returns></returns>
    public static T GetMedian<T>(T[] sourceArray, bool cloneArray = true) where T : IComparable<T>
    {
        //Framework 2.0 version of this method. there is an easier way in F4        
        if (sourceArray == null || sourceArray.Length == 0)
            throw new ArgumentException("Median of empty array not defined.");

        //make sure the list is sorted, but use a new array
        T[] sortedArray = cloneArray ? (T[])sourceArray.Clone() : sourceArray;
        Array.Sort(sortedArray);

        //get the median
        int size = sortedArray.Length;
        int mid = size / 2;
        if (size % 2 != 0)
            return sortedArray[mid];

        dynamic value1 = sortedArray[mid];
        dynamic value2 = sortedArray[mid - 1];
        return (sortedArray[mid] + value2) * 0.5;
    }

1voto

eladm Points 156

Voici l'implémentation non sécurisée la plus rapide, le même algorithme avant, pris de ceci fuente

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    private static unsafe void SwapElements(int* p, int* q)
    {
        int temp = *p;
        *p = *q;
        *q = temp;
    }

    public static unsafe int Median(int[] arr, int n)
    {
        int middle, ll, hh;

        int low = 0; int high = n - 1; int median = (low + high) / 2;
        fixed (int* arrptr = arr)
        {
            for (;;)
            {
                if (high <= low)
                    return arr[median];

                if (high == low + 1)
                {
                    if (arr[low] > arr[high])
                        SwapElements(arrptr + low, arrptr + high);
                    return arr[median];
                }

                middle = (low + high) / 2;
                if (arr[middle] > arr[high])
                    SwapElements(arrptr + middle, arrptr + high);

                if (arr[low] > arr[high])
                    SwapElements(arrptr + low, arrptr + high);

                if (arr[middle] > arr[low])
                    SwapElements(arrptr + middle, arrptr + low);

                SwapElements(arrptr + middle, arrptr + low + 1);

                ll = low + 1;
                hh = high;
                for (;;)
                {
                    do ll++; while (arr[low] > arr[ll]);
                    do hh--; while (arr[hh] > arr[low]);

                    if (hh < ll)
                        break;

                    SwapElements(arrptr + ll, arrptr + hh);
                }

                SwapElements(arrptr + low, arrptr + hh);

                if (hh <= median)
                    low = ll;
                if (hh >= median)
                    high = hh - 1;
            }
        }
    }

1voto

soxfan04 Points 11

La bibliothèque NMath de CenterSpace fournit une fonction :

double[] values = new double[arraySize];
double median = NMathFunctions.Median(values);

En option, vous pouvez choisir d'utiliser NaNMedian (si votre tableau peut contenir des valeurs nulles) mais vous devrez convertir le tableau en vecteur :

double median = NMathFunctions.NaNMedian(new DoubleVector(values));

La bibliothèque NMath de CenterSpace n'est pas gratuit, mais de nombreuses universités ont des licences

1voto

Krishneil Points 552

Un jour dans le futur. Je pense que c'est aussi simple que ça peut l'être.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Median
{
    class Program
    {
        static void Main(string[] args)
        {
            var mediaValue = 0.0;
            var items = new[] { 1, 2, 3, 4,5 };
            var getLengthItems = items.Length;
            Array.Sort(items);
            if (getLengthItems % 2 == 0)
            {
                var firstValue = items[(items.Length / 2) - 1];
                var secondValue = items[(items.Length / 2)];
                mediaValue = (firstValue + secondValue) / 2.0;
            }
            if (getLengthItems % 2 == 1)
            {
                mediaValue = items[(items.Length / 2)];
            }
            Console.WriteLine(mediaValue);
            Console.WriteLine("Enter to Exit!");
            Console.ReadKey();
        }
    }
}

0 votes

Vous pouvez en fait vous en sortir sans les instructions if. Il suffit de définir medianValue = (items[items.Length / 2] + items[(items.Length - 1) / 2])/2 . Grâce à la division entière, pour un nombre impair d'éléments dans votre tableau, vous obtiendrez simplement le même élément deux fois et lorsque vous l'ajouterez à lui-même puis le diviserez par deux, vous obtiendrez le même nombre. Pour un nombre pair d'éléments, vous obtiendrez deux index différents. Vous pouvez également envisager de laisser le tableau tel quel pour plus de clarté, mais cette façon de faire est meilleure pour la brièveté.

0voto

Prabakar Veer Points 1

Le code ci-dessous fonctionne : mais pas de manière très efficace :(

static void Main(String[] args) {
        int n = Convert.ToInt32(Console.ReadLine());            
        int[] medList = new int[n];

        for (int x = 0; x < n; x++)
            medList[x] = int.Parse(Console.ReadLine());

        //sort the input array:
        //Array.Sort(medList);            
        for (int x = 0; x < n; x++)
        {
            double[] newArr = new double[x + 1];
            for (int y = 0; y <= x; y++)
                newArr[y] = medList[y];

            Array.Sort(newArr);
            int curInd = x + 1;
            if (curInd % 2 == 0) //even
            {
                int mid = (x / 2) <= 0 ? 0 : (newArr.Length / 2);
                if (mid > 1) mid--;
                double median = (newArr[mid] + newArr[mid+1]) / 2;
                Console.WriteLine("{0:F1}", median);
            }
            else //odd
            {
                int mid = (x / 2) <= 0 ? 0 : (newArr.Length / 2);
                double median = newArr[mid];
                Console.WriteLine("{0:F1}", median);
            }
        }

}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X