C# sumowanie liczb nieparzystych z przedziału


(Ciechomski Pawel) #1

Witam! Niedawno zacząłem swoją przygodę z C#. Mam do napisania program, który będzie sumował liczby nieparzyste z danego przedziału. Napisałem go, wg mnie jest wszystko ok (ale mogę się mylić, jestem początkujący), ale niestety wyniki są nieprawidłowe. Oto kod:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;


namespace Suma_liczb_nieparzystych

{

    class Program

    {

        static void Main(string[] args)

        {

            int a, b, suma;

            suma = 0;

            Console.WriteLine("Podaj dolną granicę przedziału dodawania: ");

            a = int.Parse(Console.ReadLine());

            Console.WriteLine("Podaj górną granicę przedziału dodawania: ");

            b = int.Parse(Console.ReadLine());

            if ((a % 2) == 0)

            {

                a = (a + 1);

                do

                {

                    suma = (suma + a);

                    a = (a + 2);

                }

                while ((a - 1) >= b);

            }

            else

            {

                do

                {

                    suma = (suma + a);

                    a = (a + 2);

                }

                while ((a - 1) >= b);

            }

            Console.WriteLine("Suma liczb nieparzystych z danego przedziału wynosi: " + suma);

            Console.Read();

        }


    }

}

(Drobok) #2

Bo robisz niepotrzebne a-1 przez co masz przebieg więcej

Poza tym po co sumujesz 2x ? Jeśli a jest nie parzyste dodaj 1 i tyle w tym if, potem normalnie sumuj

cały swój przydługawy if zrezluzujesz:

for(a=!(a%2)?++a:a;a<=b;s+=a,a+=2);

-- Dodane --

(a % 2) == 0

to w if to samo co

!(a % 2)

a = (a + 1);

a++;

w rezultacie

if ((a % 2) == 0) a = (a + 1);

if (!(a % 2)) a++;

Albo warunkiem: Jak już wcześniej wspomniałem twój if w sobie zawiera za dużo (powinien zawierać tylko a++, więc 2x to samo jest zbędne:

if (!(a % 2)) a++;

                do

                {

                    suma +=a;

                    a+=2;

                }

                while (a >= b);

Poza tym powinieneś użyć for (nie trzeba dokładać linii by a+=2, poza tym warunek masz sprawdzany na końcu pętli, co przy a>b powoduje przejście pętli

//edit, ostatni code, dodany ; w pierwszej linii


(Somekindsoftware) #3

I po co tu pętla? Przecież tu wystarczy sumę ciągu arytmetycznego obliczyć, a na to jest prosty wzór.


(Ciechomski Pawel) #4

Trochę się pogubiłem, możecie wstawić pełny gotowy kod, tak będzie mi łatwiej przeanalizować, a tak już w końcu nie wiem które do którego jest :stuck_out_tongue:


(Drobok) #5

Zamień sobie cały twój if na mój pierwszy(suma=s) lub ostatni code. A jeśli chcesz wzorem o którym wspomniał somekind :

ee1c0f80f3c099c560793d5475c34876.png

suma=((!(a%2)?1+a:a)+!(b%2)?b-1:b)/2*(b-a/2+2);

wprowadzasz a,b i masz wynik :stuck_out_tongue: Niestety trzeba pamiętać że takie coś jak ten wzór istnieje :))


(Ciechomski Pawel) #6

Jejku faktycznie, zapomniałem że jest to ciąg arytmetyczny z różnicą dwa, ale gapa ze mnie :smiley: Okej, teraz już wszystko rozumiem tylko mam mały problem - przy kompilacji podaje mi błąd, że operator ! nie może być zastosowany do operandu typu int.


(Drobok) #7

Bo masz pewnie !a, zamiast !(a%2). Bo ! możesz dać tylko dla warunku logicznego / zmiennej bool


(Ciechomski Pawel) #8

Wprowadziłem dokładnie tak, jak mi napisałeś :slight_smile:

suma = ((!(a % 2) ? 1 + a : a) + !(b % 2) ? b - 1 : b) / 2 * (b - a / 2 + 2);

(Drobok) #9

Jeśli kopiowałeś ostatni code z mojego pierwszego postu, zapomniałem średnika po a++ :arrow: a++;


(Ciechomski Pawel) #10

Nie nie, robiłem tym sposobem z ciągiem.


(Drobok) #11

Daj cały kod, sprawdzałem linię w visualu i się kompiluje :))


(Ciechomski Pawel) #12
using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;


namespace Suma_liczb_nieparzystych

{

    class Program

    {

        static void Main(string[] args)

        {

            int a, b, suma;

            suma = 0;

            Console.WriteLine("Podaj dolną granicę przedziału dodawania: ");

            a = int.Parse(Console.ReadLine());

            Console.WriteLine("Podaj górną granicę przedziału dodawania: ");

            b = int.Parse(Console.ReadLine());

            suma = ((!(a % 2) ? 1 + a : a) + !(b % 2) ? b - 1 : b) / 2 * (b - a / 2 + 2);

            Console.WriteLine("Suma liczb nieparzystych z danego przedziału wynosi: " + suma);

            Console.Read();

        }


    }

}

([alex]) #13

C# to nie C !(a % 2) - nie przejdzie.

ma być: (a%2==0) w tamtym podejściu, lub:

suma=(b+a+b%2+a%2-2)*(b-a+b%2-a%2+2)/4;

(Ciechomski Pawel) #14

Wielkie dzięki wszystkim za pomoc - działa :slight_smile:

suma = (((a % 2 == 0) ? 1 + a : a) + ((b % 2 == 0) ? b - 1 : b)) / 2 * ((b - a) / (2 + 2));

-- Dodane 17.10.2013 (Cz) 13:58 --

A jednak nie, bo coś liczy źle :stuck_out_tongue:


(Drobok) #15

jednak zamiast +1 i -1 trzeba użyć ++a i --b (bo później określamy złą ilość liczb w przedziale przedział)


(Somekindsoftware) #16

To jest jakiś konkurs na najbardziej nieczytelny kod? Jaki jest sens stosować operator trójargumentowy, skoro w jednym przypadku zupełnie niczego nie zmieniasz? Gdybyś takie coś napisał u mnie w pracy, to następnego dnia musiałbyś za karę chodzić po firmie tuląc różowego jednorożca. :stuck_out_tongue: Napisałeś to tak nieczytelnie, że sam się w tym gubisz i nie wiesz czemu źle liczy. Dlaczego na siłę chcesz to wcisnąć w jedną linijkę?

using System;


namespace ConsoleApplication9

{

    class Program

    {

        static void Main(string[] args)

        {

            Console.WriteLine("Podaj dolną granicę przedziału dodawania: ");

            int a = int.Parse(Console.ReadLine());

            Console.WriteLine("Podaj górną granicę przedziału dodawania: ");

            int b = int.Parse(Console.ReadLine());


            // jeśli liczby są parzyste, trzeba coś z tym zrobić:

            if (a % 2 == 0)

                a += 1;

            if (b % 2 == 0)

                b -= 1;


            int n = ((b - a) / 2 + 1); // liczba liczb nieparzystych między a i b

            int suma = ((a + b) / 2) * n; // z wzoru, który wszyscy znają


            Console.WriteLine("Suma liczb nieparzystych z danego przedziału wynosi: " + suma);

            Console.Read();

        }

    }

}

(Drobok) #17
i nie wiesz czemu źle liczy

teraz już wiem, ale to nie kwestia tej jednej linii, a moich umiejętności matematycznych :))


([alex]) #18

Jestem zwolennikiem optymalizacji, na to samo wyjdzie jednak bez if'ów:

using System;


namespace ConsoleApplication9

{

    class Program

    {

        static void Main(string[] args)

        {

            Console.WriteLine("Podaj dolną granicę przedziału dodawania: ");

            int a = int.Parse(Console.ReadLine());

            Console.WriteLine("Podaj górną granicę przedziału dodawania: ");

            int b = int.Parse(Console.ReadLine());


            int suma=((b+=b&1)*b-(a-=a&1)*a)>>2; // rozpisane niżej

            //a-=a&1;

            //b+=b&1;

            //int suma=(b*b-a*a)>>2;


            Console.WriteLine("Suma liczb nieparzystych z danego przedziału wynosi: " + suma);

            Console.Read();

        }

    }

}

(Grzelix) #19

Widzę że temat już raczej rozpracowany ale dodam swoją propozycję.

public int sumEvenNumberFromRange(int a, int b){

            return Enumerable.Range(a, b - a + 1).Where(n => n%2 != 0).Sum();

        }

([alex]) #20

grzelix , gorszego wariantu nie da się spłodzić.