Προς το περιεχόμενο

C#: Πρόγραμμα υπολογισμού μέσου όρου.


costgial

Προτεινόμενες αναρτήσεις

Δημοσ. (επεξεργασμένο)

Καλησπέρα σας και καλή χρονιά να έχετε όλοι σας παιδιά, με ευτυχία και υγεία.
Παρακάτω θα δείτε ένα πρόγραμμα υπολογισμού του μέσου όρου από τον συνολικό αριθμό αριθμών που εισάγει ο χρήστης το οποίο το έφτιαξε με τις πιο βασικές γνώσεις που έχω αποκτήσει έως τώρα στη C#. 
Από εσάς θέλω τη γνώμη σας και τα σχόλια σας :)

using System;

namespace Averager
{
    class Program
    {
        static void Main(string[] args)
        {


            var runningTotal = 0.0;
            var countEntries = 0;


            while (true)
            {
                Console.Write("Enter a number to see the average or type \"quit\" to exit: ");
                var entry = Console.ReadLine();


                if (entry.ToLower() == "quit")
                {
                    break;
                }
                else
                {
                    try
                    {
                        var number = double.Parse(entry);

                        runningTotal += number;

                        if (entry != "0")
                        {
                            countEntries++;
                        }

                    }
                    catch (FormatException)
                    {
                        Console.WriteLine("Please type a valid numeric value");
                        continue;
                    }
                }

                Console.WriteLine("Your average = " + runningTotal / (double)countEntries);
                //Console.WriteLine(countEntries); //ο συνολικός αριθμός εισόδων αριθμών από τον χρήστη για τον υπολογισμό του μέσου όρου
            }

        }
    }
}

 

Επεξ/σία από costgial
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Μπορείς να αποφύγεις το άθροισμα γιατί στην ακραία περίπτωση που ο χρήστης σου δώσει πάρα πολλές τιμές ή και λιγότερες άλλα πολύ μεγάλες προκαλειται το φαίνομενο overflow (Google it) για αυτό καλό είναι να χρησιμοποιείς έναν τύπο για rolling average (Google it again :D)

  • Thanks 1
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Δημοσ. (επεξεργασμένο)

Σωστή είναι η εκτέλεση σου, μια αλλαγή που θα πρότεινα, είναι αντί για το try.... catch, να χρησιμοποιούσες 

if(double.Tryparse(out var number)){}

else{}

Είναι σίγουρα πιο elegant από το να χειρίζεσαι το User Inputs με εξεπτιονς’ και το όλο προγράμμα είναι πιο συμμαζεμένο.

Επεξ/σία από Papakaliati
  • Like 1
  • Thanks 1
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

8 ώρες πριν, solarpower είπε

Ο μέσος όρος βγαίνει με τον προηγούμενο μέσο όρο συν την νέα τιμή και αυτό το άθροισμα το διαιρούμε δια δύο.

Κανε μια δοκιμη πριν το γραψεις. πχ για input [1, 2, 3] 

  • Like 1
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Δημοσ. (επεξεργασμένο)

 

3 ώρες πριν, Kercyn είπε

Γιατί η τιμή 0 δεν είναι έγκυρη και δεν τη μετράς; Δηλαδή άμα έχω 10 0 0 0, ο μέσος όρος είναι 10 και όχι 2.5;

Ευχαριστώ για την παρατήρηση!

Καλή χρονιά σε όλους!

Επεξ/σία από costgial
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Διόρθωσα το λαθάκι με το 0. Επίσης νομίζω ότι συμπεριέλαβα το overflowexception στο try...catch μέχρι να μάθω τι γίνεται με τα rolling averages και το 

if(double.Tryparse(out var number)){}

else{}

using System;

namespace Averager
{
    class Program
    {
        static void Main(string[] args)
        {


            var runningTotal = 0.0;
            var countEntries = 0;


            while (true)
            {
                Console.Write("Enter a number or type \"done\" to see the average (or type \"quit\" to exit): ");
                var entry = Console.ReadLine();


                if (entry.ToLower() == "done")
                {
                    
                }
                else if (entry.ToLower() == "quit")
                {

                }

                else
                {
                    try
                    {
                        var number = double.Parse(entry);

                        runningTotal += number;

                        countEntries++;

                    }
                    catch (Exception ex)
                    {
                        if (ex is FormatException || ex is OverflowException)
                        { 
                        Console.WriteLine("Please type a valid numeric value");
                        continue;
                        }
                    }
                }

                if ( entry.ToLower() == "done")
                {
                    Console.WriteLine("Average = " + runningTotal / (double)countEntries);

                }
                else if (entry.ToLower() == "quit")
                {
                    break;
                }


                //Console.WriteLine(countEntries); //ο συνολικός αριθμός εισόδων αριθμών από τον χρήστη για τον υπολογισμό του μέσου όρου

            }

        }
    }
}

Όπως βλέπετε το πρώτο if και else if είναι κενά και τα χρησιμοποιώ ξανά προς το τέλος του κώδικα. Αυτό το έκανα, γιατί αν τα έσβηνα από την αρχή και τα έγραφα κατευθείαν προς το τέλος μου έβγαζε το μήνυμα "Please type a valid numeric value" που περιέχεται στο catch(), όταν πληκτρολογούσα "done" ή "quit". Κάτι δεν έχω καταλάβει μάλλον και θέλω λίγη βοήθεια.

  • Like 1
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

catch (Exception ex)
{
    if (ex is FormatException || ex is OverflowException)
    { 
        Console.WriteLine("Please type a valid numeric value");
        continue;
    }
}

Δεν είναι καλός τρόπος αυτός.

Καταρχήν γενικά μιλώντας, δεν κάνουμε catch Exception γιατί μπορεί να είναι οτιδήποτε exception, ακόμα και πράγματα που και να τα κάνεις catch πάλι θα τερματίσουν την εφαρμογή. Το catch (Exception) είναι λοιπόν και παραπλανητικό (νομίζεις ότι καθάρισες ο,τι κι αν γίνει) και λάθος (αφού δεν ξέρεις τι έπιασες και δεν ξέρεις ούτε πώς να το χειριστείς ούτε τι συνέπειες θα έχει για την εφαρμογή).

Σε πρόσφατες εκδόσεις C# μπορείς να γράψεις

catch (Exception e) when (e is FormatException || e is OverflowException)

το οποίο είναι πολύ βολικό. Διαφορετικά, μη ξεχνάς τουλάχιστον αν αποτύχει το if να κάνεις πάλι throw. Όχι πως έχει κάποια πρακτική σημασία σ' αυτό το πρόγραμμα, απλά είναι καλή πρακτική.

Απο κει και πέρα, δε νομίζω πως υπάρχει καθόλου λόγος για try/catch εδώ.

Πρώτον το FormatException το γλυτώνεις με TryParse (βολικότερο), και δεύτερον το OverflowException που υποθέτω πάει στην πρόσθεση του runningTotal άντε και το έπιασες, μετά τι; Λάθος error message και δε μπορείς να κάνεις και τίποτα για να το λύσεις αφού ο αριθμός που θες να προσθέσεις θα το προκαλεί πάντα.

Επίσης αν το καλοσκεφτείς έχεις bug επειδή θεωρητικά μπορεί να κάνει overflow και το runningTotal αλλά και το countEntries. Επομένως με οποιαδήποτε σειρά και να βάλεις τις προσθέσεις, μπορεί η πρώτη να πετύχει και η δεύτερη να κάνει overflow, πράγμα που θα οδηγήσει στην επανάληψη του κώδικα αλλά πλέον με λάθος δεδομένα (η άλλη πρόσθεση που έχει κρατηθεί θα σου έχει χαλάσει τα νούμερα). Από τη στιγμή λοιπόν που μπαίνεις στον κόπο να πιάσεις OverflowException και να συνεχίσεις την εκτέλεση, φρόντισε να το έχεις πιάσει απ' όλες τις μεριές.

Επιπλέον, αν ο χρήστης δώσει done από την αρχή τότε countEntries == 0 και DivideByZeroException. Και τέλος, γιατί δεν περνάς τον κώδικα που έχεις στα "δεύτερα" if μέσα στα πρώτα που είναι τώρα κενά, και να πετάξεις τα δεύτερα τελείως;

  • Thanks 1
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

1 ώρα πριν, defacer είπε

catch (Exception ex)
{
    if (ex is FormatException || ex is OverflowException)
    { 
        Console.WriteLine("Please type a valid numeric value");
        continue;
    }
}

Δεν είναι καλός τρόπος αυτός.

Καταρχήν γενικά μιλώντας, δεν κάνουμε catch Exception γιατί μπορεί να είναι οτιδήποτε exception, ακόμα και πράγματα που και να τα κάνεις catch πάλι θα τερματίσουν την εφαρμογή. Το catch (Exception) είναι λοιπόν και παραπλανητικό (νομίζεις ότι καθάρισες ο,τι κι αν γίνει) και λάθος (αφού δεν ξέρεις τι έπιασες και δεν ξέρεις ούτε πώς να το χειριστείς ούτε τι συνέπειες θα έχει για την εφαρμογή).

Σε πρόσφατες εκδόσεις C# μπορείς να γράψεις


catch (Exception e) when (e is FormatException || e is OverflowException)

το οποίο είναι πολύ βολικό. Διαφορετικά, μη ξεχνάς τουλάχιστον αν αποτύχει το if να κάνεις πάλι throw. Όχι πως έχει κάποια πρακτική σημασία σ' αυτό το πρόγραμμα, απλά είναι καλή πρακτική.

Απο κει και πέρα, δε νομίζω πως υπάρχει καθόλου λόγος για try/catch εδώ.

Πρώτον το FormatException το γλυτώνεις με TryParse (βολικότερο), και δεύτερον το OverflowException που υποθέτω πάει στην πρόσθεση του runningTotal άντε και το έπιασες, μετά τι; Λάθος error message και δε μπορείς να κάνεις και τίποτα για να το λύσεις αφού ο αριθμός που θες να προσθέσεις θα το προκαλεί πάντα.

Επίσης αν το καλοσκεφτείς έχεις bug επειδή θεωρητικά μπορεί να κάνει overflow και το runningTotal αλλά και το countEntries. Επομένως με οποιαδήποτε σειρά και να βάλεις τις προσθέσεις, μπορεί η πρώτη να πετύχει και η δεύτερη να κάνει overflow, πράγμα που θα οδηγήσει στην επανάληψη του κώδικα αλλά πλέον με λάθος δεδομένα (η άλλη πρόσθεση που έχει κρατηθεί θα σου έχει χαλάσει τα νούμερα). Από τη στιγμή λοιπόν που μπαίνεις στον κόπο να πιάσεις OverflowException και να συνεχίσεις την εκτέλεση, φρόντισε να το έχεις πιάσει απ' όλες τις μεριές.

Επιπλέον, αν ο χρήστης δώσει done από την αρχή τότε countEntries == 0 και DivideByZeroException. Και τέλος, γιατί δεν περνάς τον κώδικα που έχεις στα "δεύτερα" if μέσα στα πρώτα που είναι τώρα κενά, και να πετάξεις τα δεύτερα τελείως;

Καταρχάς σε ευχαριστώ πολύ για την απάντηση σου. Προσπαθώ να μπω στο κλίμα του προγρμματισμού μέσα από αυτά που έχω μάθει έως τώρα, χωρίς να ανατρέχω στο msdn (προς το παρών), διότι εξασκώ και τα αγγλικά μου παράλληλα. Αυτό σημαίνει ότι πολλά από αυτά δεν τα καταλαβαίνω με βάσει αυτά που έχω μάθει, όμως τα ψάχνω και καταλαβαίνω περίπου τι παίζει.

Το try...catch το έμαθα, για να αποφύγω το format exception που έβγαινε όταν ζητούσα από τον χρήστη αριθμό και αυτός πληκτρολογούσε οτιδήποτε άλλο, οπότε είπα να το χρησιμοποιήσω και σε αυτήν την περίπτωση.

Το overflowexception και το DividedByZeroException προς το παρών απλώς υπάρχουν, καθώς δεν τα έχω καταλάβει ακόμη αρκετά. 

 

using System;

namespace Averager
{
    class Program
    {
        static void Main(string[] args)
        {


            var runningTotal = 0.0;
            var countEntries = 0;


            while (true)
            {
                Console.Write("Enter a number or type \"done\" to see the average (or type \"quit\" to exit): ");
                var entry = Console.ReadLine();
                

                if (entry.ToLower() == "done")
                {
                    Console.WriteLine("Average = " + runningTotal / (double)countEntries + " (Enter another number to add it to your average)");
                }
                else if (entry.ToLower() == "quit")
                {
                    break;
                }

                else
                {
                    try
                    {
                        var number = double.Parse(entry);

                        runningTotal += number;

                        countEntries++;

                    }
                    catch (Exception e) when (e is FormatException || e is OverflowException || e is DivideByZeroException)
                    {
                        Console.WriteLine("Please type a valid numeric value");
                        continue; 
                    }
                }

                //Console.WriteLine(countEntries); //ο συνολικός αριθμός εισόδων αριθμών από τον χρήστη για τον υπολογισμό του μέσου όρου

            }

        }
    }
}

 

 

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

        static void Main(string[] args)
        {
            double runningTotal = 0.0;
            double countEntries = 0.0;

            while (true)
            {
                Console.Write("Enter a number to see the average or type \"quit\" to exit: ");
                var entry = Console.ReadLine();

                if (!entry.ToLower().Equals("quit"))
                {
                    //is a number?
                    double number = 0.0;
                    bool isANumber = double.TryParse(entry, out number);

                    if (isANumber)
                    {
                        //avoid overflow
                        if (number < Double.MinValue)
                        {
                            number = Double.MinValue;
                        }
                        
                        if (number > Double.MaxValue)
                        {
                            number = Double.MaxValue;
                        }

                        runningTotal += number;
                        countEntries++;
                        Console.WriteLine($"Your average = {runningTotal / countEntries}");
                        Console.WriteLine($"Count entries = {countEntries}");
                    }
                }
                else
                {
                    break;
                }
            }
        }

Καταθέτω και εγώ τον όβολο μου. καλή χρονιά σε όλους

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

57 λεπτά πριν, Kostas Palaiologos είπε

        static void Main(string[] args)
        {
            double runningTotal = 0.0;
            double countEntries = 0.0;

            while (true)
            {
                Console.Write("Enter a number to see the average or type \"quit\" to exit: ");
                var entry = Console.ReadLine();

                if (!entry.ToLower().Equals("quit"))
                {
                    //is a number?
                    double number = 0.0;
                    bool isANumber = double.TryParse(entry, out number);

                    if (isANumber)
                    {
                        //avoid overflow
                        if (number < Double.MinValue)
                        {
                            number = Double.MinValue;
                        }
                        
                        if (number > Double.MaxValue)
                        {
                            number = Double.MaxValue;
                        }

                        runningTotal += number;
                        countEntries++;
                        Console.WriteLine($"Your average = {runningTotal / countEntries}");
                        Console.WriteLine($"Count entries = {countEntries}");
                    }
                }
                else
                {
                    break;
                }
            }
        }

Καταθέτω και εγώ τον όβολο μου. καλή χρονιά σε όλους

Ευχαριστώ πάρα πολύ!! :-D

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Δημοσ. (επεξεργασμένο)

costgial

Ευχαριστώ γιατί δίνεις τροφή για σκέψη :)

Να πούμε επίσης ότι υπάρχει και η συνάρτηση Average() που επιστρέφει μέσo όρο για περιπτώσεις που έχουμε μεγάλα array με πολλές τιμές οπότε έκανα και εγώ ένα script που κάνω τη δουλεία με array χωρίς όμως ελέγχους για την είσοδο

static void Main(string[] args)
        {
            Console.WriteLine("Δώσε αριθμούς για να υπολογίσω τον μέσo όρο (quit για έξοδο) ");
            string entry;
            var arithmoi = new List<double>(); 
            while ((entry = Console.ReadLine()) != "quit")
                arithmoi.Add(Double.Parse(entry));
            Console.WriteLine($"Ο μέσος όρος των {arithmoi.Count} αριθμών που έδωσες και έχει άθροισμα {arithmoi.Sum()} είναι {arithmoi.Average()}");
        }

 

Επεξ/σία από k33theod
List αντί array
  • Like 1
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

6 ώρες πριν, costgial είπε

μέχρι να μάθω τι γίνεται με τα rolling averages

Νομίζω μπορεί να γίνει μόνο αν ξέρεις εξαρχής τον αριθμό των στοιχείων

αν ξέρεις δηλαδή ότι θα χρησιμοποιηθούν δέκα στοιχεία 

(a1+a2+...+a10)/10 =a1/10+a2/10+...+a10/10 ouaou

 

  • Like 1
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Δημοσ. (επεξεργασμένο)

Δεν χρειάζεται να ξέρεις τον πλήθος από την αρχή.

Επίσης το να βάλεις περιορισμο για το πόσα θα βάλει ο χρωστάω είναι σαν να ξεκινάς με goal από τα αποδυτήρια.

Υ. Γ. Προφανώς αυτά για κανονική εφαρμογή και όχι για αυτό που μιλάμε αλλα good practices.

Επεξ/σία από kaliakman
  • Like 1
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε

Πρέπει να είστε μέλος για να αφήσετε σχόλιο

Δημιουργία λογαριασμού

Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!

Δημιουργία νέου λογαριασμού

Σύνδεση

Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.

Συνδεθείτε τώρα
  • Δημιουργία νέου...