C # में पूर्णांकों की एक सरणी का योग कैसे करें


108

वहाँ सरणी पर पुनरावृत्ति से बेहतर एक बेहतर तरीका है?

int[] arr = new int[] { 1, 2, 3 };
int sum = 0;
for (int i = 0; i < arr.Length; i++)
{
    sum += arr[i];
}

स्पष्टीकरण:

बेहतर प्राथमिक का मतलब है क्लीनर कोड लेकिन प्रदर्शन में सुधार के संकेत भी स्वागत योग्य हैं। (जैसा कि पहले ही उल्लेख किया गया है: बड़े सरणियों को विभाजित करना)।


ऐसा नहीं है कि मैं हत्यारे के प्रदर्शन में सुधार की तलाश कर रहा था - मुझे आश्चर्य है कि अगर यह बहुत ही प्रकार की सिंथैटिक चीनी पहले से उपलब्ध नहीं थी: "वहाँ स्ट्रिंग है। जॉइन - इंट [] के बारे में क्या बिल्ली?"।


2
किस तरीके से बेहतर है? और तेज? कम लिखा कोड?
फ्रेड्रिक मोर्क

जवाबों:


186

बशर्ते कि आप .NET 3.5 (या नए) और LINQ का उपयोग कर सकते हैं, प्रयास करें

int sum = arr.Sum();

10
पहचान लैम्ब्डा आवश्यक नहीं है। टीम पर नए आदमी को भ्रमित करने के लिए छोड़कर।

12
यह ध्यान देने योग्य है कि यह एक त्रुटि प्राप्त करेगा System.OverflowExceptionयदि परिणाम आपके द्वारा हस्ताक्षरित 32 बिट पूर्णांक (यानी (2 ^ 31) -1 या अंग्रेजी ~ 2.1 बिलियन) में फिट हो सकता है।
क्रिसपॉसर

2
int sum = arr.AsParallel().Sum();एक तेज संस्करण जो CPU के कई कोर का उपयोग करता है। से बचने के लिए System.OverflowExceptionआप उपयोग कर सकते हैं long sum = arr.AsParallel().Sum(x => (long)x);कि बचने अतिप्रवाह अपवाद भी तेजी से संस्करणों के लिए और समर्थन सभी पूर्णांक डेटा प्रकार और उपयोग डेटा समानांतर SIMD / SSE निर्देश, HPCsharp nuget पैकेज पर एक नज़र डालें
DragonSpit

66

हाँ वहाँ है। .NET 3.5 के साथ:

int sum = arr.Sum();
Console.WriteLine(sum);

यदि आप .NET 3.5 का उपयोग नहीं कर रहे हैं, तो आप ऐसा कर सकते हैं:

int sum = 0;
Array.ForEach(arr, delegate(int i) { sum += i; });
Console.WriteLine(sum);

2
क्यों इस तरह के एक पूर्व निर्धारित 3.5 संस्करण? foreachपाश सी # के सभी संस्करणों में उपलब्ध है।
जॉर्न शॉ-रोड

2
@ जोर्न: ओपी ने एक छोटे दृष्टिकोण के लिए कहा। एक foreachकोड दूसरे के लिए एक लाइन का विकल्प देता है और छोटा नहीं होता। इसके अलावा एक foreachपूरी तरह से ठीक है और अधिक पठनीय है।
अहमद मगेद

2
मुद्दा लेना। फिर भी, निम्नलिखित आपके नमूने की तुलना में 18 foreach (int i in arr) sum += i;
चार्ट


5

यह इस बात पर निर्भर करता है कि आप बेहतर कैसे परिभाषित करते हैं। यदि आप चाहते हैं कि कोड साफ-सुथरा दिखे, तो आप उपयोग कर सकते हैं। यदि आप चाहते हैं कि ऑपरेशन शीघ्रता से चले और आपके पास एक बड़ा सरणी हो, तो आप इसे उप योगों में तोड़कर समानांतर बना सकते हैं और फिर परिणाम प्राप्त कर सकते हैं।


+1 प्रदर्शन सुधार पर बहुत अच्छी बात है, लेकिन ईमानदारी से मेरी प्रारंभिक इच्छा पुनरावृति से छुटकारा पाने की थी।
फिल्मबर्ट

(किसी ने फिल को यह नहीं बताया कि उसने सिर्फ पुनरावृति को एक स्तर से कुछ नीचे धकेल दिया था)

@Will: यार - मुझे उम्मीद नहीं है कि अगर मैं कोड नहीं लिखूंगा तो जादू होगा; ;-)
Filburt

3
मुझे संदेह है कि इस तरह के समानांतर अनुकूलन से पहले बहुत बड़ी सरणी होगी।
इयान मर्सर

हाँ, लूप के लिए कब से बुरा अभ्यास हो गया?
एड एस।

3

एक विकल्प यह भी Aggregate()विस्तार विधि का उपयोग करने के लिए ।

var sum = arr.Aggregate((temp, x) => temp+x);

1
यह काम करने के लिए लगता है जहां योग नहीं है। यह किसी कारण के लिए यूंट की एक सरणी पर काम नहीं करेगा लेकिन एग्रीगेट करेगा।
जॉन अर्नेस्ट

2

यदि आप LINQ पसंद नहीं करते हैं, तो इंडेक्स से बचने के लिए foreach पाश का उपयोग करना बेहतर है।

int[] arr = new int[] { 1, 2, 3 };
int sum = 0;
foreach (var item in arr)
{
   sum += item;
}

2

बहुत बड़ी सरणियों के लिए यह मशीन के एक से अधिक प्रोसेसर / कोर का उपयोग करके गणना करने के लिए भुगतान कर सकता है।

long sum = 0;
var options = new ParallelOptions()
    { MaxDegreeOfParallelism = Environment.ProcessorCount };
Parallel.ForEach(Partitioner.Create(0, arr.Length), options, range =>
{
    long localSum = 0;
    for (int i = range.Item1; i < range.Item2; i++)
    {
        localSum += arr[i];
    }
    Interlocked.Add(ref sum, localSum);
});

2

उपरोक्त लूप समाधानों के लिए एक समस्या यह है कि सभी सकारात्मक मूल्यों के साथ निम्नलिखित इनपुट सरणी के लिए, योग परिणाम नकारात्मक है:

int[] arr = new int[] { Int32.MaxValue, 1 };
int sum = 0;
for (int i = 0; i < arr.Length; i++)
{
    sum += arr[i];
}
Console.WriteLine(sum);

यह राशि -2147483648 है, क्योंकि सकारात्मक परिणाम इंट डेटा प्रकार के लिए बहुत बड़ा है और एक नकारात्मक मूल्य में ओवरफ्लो करता है।

एक ही इनपुट ऐरे के लिए अरेस्ट () सुझाव ओवरफ्लो अपवाद को फेंकने का कारण बनता है।

एक अधिक मजबूत समाधान एक बड़े डेटा प्रकार का उपयोग करना है, जैसे कि "योग" इस मामले में, "योग" के लिए निम्नानुसार है:

int[] arr = new int[] { Int32.MaxValue, 1 };
long sum = 0;
for (int i = 0; i < arr.Length; i++)
{
    sum += arr[i];
}

एक ही सुधार अन्य पूर्णांक डेटा प्रकारों के संक्षेपण के लिए काम करता है, जैसे कि संक्षिप्त और संक्षिप्त। अहस्ताक्षरित पूर्णांक डेटा प्रकारों जैसे कि uint, ushort और बाइट के सरणियों के लिए, योग के लिए अहस्ताक्षरित लंबे (ulong) का उपयोग ओवरफ़्लो अपवाद से बचा जाता है।

लूप समाधान के लिए भी Linq .Sum () से कई गुना तेज है

और भी तेज चलाने के लिए, HPCsharp नगेट पैकेज इन सभी .Sum () संस्करणों के साथ-साथ SIMD / SSE संस्करणों और मल्टी-कोर समानांतर वाले, कई बार तेज प्रदर्शन के लिए लागू करता है।


महान विचार। और, अहस्ताक्षरित पूर्णांक सरणी के लिए यह उल्टा योग = गिरफ्तारी करने में सक्षम होना अच्छा होगा। (x => (ulong) x); लेकिन, दुख की बात है कि Linq .Sum () अहस्ताक्षरित पूर्णांक डेटा प्रकारों का समर्थन नहीं करता है। यदि अहस्ताक्षरित योग की आवश्यकता है, तो HPCsharp नगेट पैकेज सभी अहस्ताक्षरित डेटा प्रकारों के लिए इसका समर्थन करता है।
ड्रैगनस्पिट

एक योगदानकर्ता ने एक अच्छा विचार वापस ले लिया, long sum = arr.Sum(x => (long)x);जो Linq का उपयोग करके C # में अच्छी तरह से काम करता है। यह सभी हस्ताक्षरित पूर्णांक डेटा प्रकारों के लिए पूर्ण सटीकता प्रदान करता है: sbyte, short, और int। यह भी एक अतिप्रवाह अपवाद फेंकने से बचता है, और अच्छी तरह से कॉम्पैक्ट है। यह लूप के लिए ऊपर के रूप में उच्च प्रदर्शन नहीं है, लेकिन सभी मामलों में प्रदर्शन की आवश्यकता नहीं है।
ड्रैगनस्पिट

0

फॉर्च्यूनर का उपयोग करना कम कोड होगा, लेकिन JIT ऑप्टिमाइजेशन के लिए लूप कंट्रोल अभिव्यक्ति में लंबाई की तुलना को पहचानने के बाद रनटाइम के दौरान ठीक वैसा ही कदम होगा।


0

मेरे द्वारा उपयोग किए जाने वाले मेरे एक ऐप में:

public class ClassBlock
{
    public int[] p;
    public int Sum
    {
        get { int s = 0;  Array.ForEach(p, delegate (int i) { s += i; }); return s; }
    }
}

यह .Aggregate()एक्सटेंशन विधि का उपयोग करने के समान है ।
जॉन अलेक्सियो

-1

थियोडोर ज़ूलियास के अच्छे मल्टी-कोर समानांतर पर एक सुधार। कार्यान्वयन लागू करें:

    public static ulong SumToUlongPar(this uint[] arrayToSum, int startIndex, int length, int degreeOfParallelism = 0)
    {
        var concurrentSums = new ConcurrentBag<ulong>();

        int maxDegreeOfPar = degreeOfParallelism <= 0 ? Environment.ProcessorCount : degreeOfParallelism;
        var options = new ParallelOptions() { MaxDegreeOfParallelism = maxDegreeOfPar };

        Parallel.ForEach(Partitioner.Create(startIndex, startIndex + length), options, range =>
        {
            ulong localSum = 0;
            for (int i = range.Item1; i < range.Item2; i++)
                localSum += arrayToSum[i];
            concurrentSums.Add(localSum);
        });

        ulong sum = 0;
        var sumsArray = concurrentSums.ToArray();
        for (int i = 0; i < sumsArray.Length; i++)
            sum += sumsArray[i];

        return sum;
    }

जो अहस्ताक्षरित पूर्णांक डेटा प्रकारों के लिए काम करता है, क्योंकि C # केवल इंटरलॉक किए गए समर्थन करता है। () इंट और लंबे समय के लिए। उपरोक्त कार्यान्वयन को आसानी से सीपीयू के कई कोर का उपयोग करके समांतर करने के लिए अन्य पूर्णांक और फ्लोटिंग-पॉइंट डेटा प्रकारों का समर्थन करने के लिए संशोधित किया जा सकता है। इसका उपयोग HPCsharp नगेट पैकेज में किया जाता है।


-7

इस कोड को आज़माएं:

using System;

namespace Array
{
    class Program
    {
        static void Main()
        {
            int[] number = new int[] {5, 5, 6, 7};

            int sum = 0;
            for (int i = 0; i <number.Length; i++)
            {
                sum += number[i];
            }
            Console.WriteLine(sum);
        }
    }
} 

परिणाम है:

23


आपका कोड सही नहीं है, आपको Console.WriteLine (sum) को बदलना होगा; वापसी राशि के साथ; और यह काम करेगा
अब्देसमद जदीद
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.