Liczba doskonała

0

No dobra mam do napisania programik w ktorym to maja zostac pokazane liczby doskonałe. Poniżej program określa czy podana liczba jest doskonałą czy też nie. Problem polega na tym aby był przedział od <1,n> i z tego przedziału pokazują się wszystkie liczby doskonałe. Kombinowałem aby wstawić przed petlą for jeszcze jedną pętle for (int n=1; n<w; n++) a za początkową zmienną którą określa użytkownik wstawić "w" ale kompilator podaje złe wyniki. Nie wiem dlaczego, z moje punktu widzenia przecież najpierw określa czy 1jest liczba doskonałą poźniej 2,3,4 itd. Jak to zapisać? Podpowie ktoś ?

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

namespace Zadanie_3._14petle
{
    class Program
    {
        /* liczba N jest doskonala, gdy jest rowna sumie swych podzielnikow mniejszych od niej samej np=6 bo 
         * +1+2+3=6
         * Szesc jest liczba doskonała. Napisz program znajdujacy liczby doskonałe w przedziale od <1,n>
         * gdzie n podaje uzytkownika
         * */

            /*
             * trzeba znalezc wszystkie dzielniki liczby n
             * Nastepnie nalezy dodac wszystkie dzielniki oprocz najwiekszego
             * Jezeli suma dodanych dzielnikow rowna sie liczbie N tzn. Ze jest to liczba doskonała
             * */
        static void Main(string[] args)
        {
            Console.WriteLine("Program znajdzie dla ciebie liczby doskonale!");
            Console.WriteLine("Podaj przedział od <1,n>");
            Console.WriteLine("Podaj N:");
            int n;
          int suma=0;
            n = int.Parse(Console.ReadLine());

         
                for (int i = 1; i < n; i++)
                {
                    if (n % i == 0)
                    {
                        Console.WriteLine(i);
                        suma = suma + i;
                    if (suma == n)
                    {
                        Console.WriteLine("Liczba {0} jest liczbą doskonałą", n);
                    }
                    
                    }
                }
         
            
            Console.ReadKey();
        }
    }
}
2

Spróbuj myśleć o jednym problemie na raz, a resztą zająć się po wykonaniu tego, co obecnie robisz. Idź w kierunku od najbardziej ogólnych czynności do najbardziej szczegółowych.

1. Napisz funkcję, która wyświetla komunikaty i pobiera liczbę, a następnie dla wszystkich liczb od 1 do N sprawdza, czy są liczbami doskonałymi:

static void Main()
{
    int N = 0;

    Console.WriteLine("Program znajdzie dla ciebie liczby doskonale z przedziału <1, N>!");

    do
    {
        Console.Write("Podaj N: ");
        if (!int.TryParse(Console.ReadLine(), out N))
            Console.WriteLine("Nie podałeś prawidłowej liczby!");
    }
    while (N == 0);

    for (int i = 1; i <= N; i++)
        if (IsPerfectNumber(i))
            Console.WriteLine("Liczba {0} jest liczbą doskonałą", i);

    Console.ReadKey();
}

Wykorzystałem pętlę, która przestanie się wykonywać dopiero wtedy, gdy wartość zmiennej N będzie różna od jej początkowej wartości 0. Metoda int.TryParse zwraca wartość true, jeśli ciąg znaków można zamienić na liczbę całkowitą, lub false w przeciwnym przypadku.

2. Powyżej wywołałem funkcję IsPerfectNumber, która z założenia przyjmuje liczbę typu int i zwraca true, jeśli liczba i jest liczbą doskonałą, lub false w przeciwnym przypadku. Taką funkcję trzeba napisać:

private static bool IsPerfectNumber(int x)
{
    if (GetAllFactors(x).Sum() == x)
        return true;
    return false;
}

Ta funkcja sprawdza, czy suma wszystkich dzielników podanej liczby jest równa tej liczbie.

3. Powyżej wywołałem funkcję GetAllFactors, która z założenia przyjmuje liczbę typu int i zwraca listę dzielników tej liczby. Taką funkcję trzeba napisać:

private static List<int> GetAllFactors(int x)
{
    List<int> factors = new List<int>();
    for (int f = 1; f < x; f++)
        if (IsFactor(x, f))
            factors.Add(f);
    return factors;
}

4. Powyżej wywołałem funkcję IsFactor, która z założenia przyjmuje dwie liczby typu int i zwraca wartość true, jeśli pierwsza liczba jest podzielna przez drugą liczbę, lub false w przeciwnym przypadku. Taką funkcję trzeba napisać:

private static bool IsFactor(int x, int f)
{
    if (x % f == 0)
        return true;
    return false;
}

Ogólnie chodziło mi o to, żeby problem rozłożyć na kilka oddzielnych problemów i myśleć o rozwiązaniu jednego problemu na raz. Żeby sprawdzić, czy rozwiązanie któregoś z problemów działa przed zaimplementowaniem kolejnych funkcji, możesz zwracać z takich funkcji specjalnie spreparowane dane, które będą zgadzały się z Twoim przypadkiem.

Metoda IEnumerable<int>.Sum korzysta z biblioteki System.Linq, więc będziesz musiał ją dołączyć za pomocą słowa kluczowego using lub napisać własną funkcję sumującą wszystkie liczby z listy.

0

Dzięki dość sporo nowych informacji. A nie dałoby rady wstawić w ten kod co napisałem jeszcze przedziału, no bo to co zapisałem pokazuje czy liczba jest doskonała czy nie. Np wpisze 6 to wyświetli mi się komunikat że jest to liczba doskonała, wpisze 5 nie wyświetli że to liczba doskonała. Czyli w moim zrozumieniu gdybym wstawił za "n" najpierw 1, potem,2,3,4,itd aż do osiągnięcia wartości którą wprowadzi użytkownik to by wypisało wszystkie liczby doskonałe. Nie rozumiem dlaczego kod nie działa gdy wrzucą przed pętla for jeszcze jedną pętle for która zwiększa mi n o jeden za każdym razem aż do osiągnięcia liczby którą wprowadził użytkownik. Pomoże ktoś ?

4

W Twoim kodzie jest dużo do poprawy, żeby sprawić, żeby program działał tak, jak chcesz. Wymienię po kolei, co według mnie powinieneś zmienić.

  1. Instrukcja warunkowa if (suma == n) sprawdza, czy suma dotychczas znalezionych dzielników jest równa sprawdzanej liczbie przed zakończeniem pętli, dlatego np. Twój program pokazuje, że 24 jest liczbą doskonałą zanim dojdzie do dzielnika 12, dlatego go nie uwzględnia. Dlatego powinieneś przenieść ten warunek za pętlę.
  2. Żeby program sprawdzał każdą liczbę od 1 do n, powinieneś umieścić Twoją pętlę i warunek w jeszcze jednej pętli, a zmienną suma zerować w każdym kroku tej zewnętrznej pętli, żeby nie uwzględniała dzielników dla poprzednio sprawdzanych liczb. Twoją zmienną, która jest licznikiem pętli, nazwę j, a nową i.
  3. Wyświetlanie w każdej linii wszystkich sprawdzanych dzielników psuje czytelność.
  4. Funkcja System.WriteLine wyświetlająca napis "Podaj N:" może być zamieniona na System.Write z dodaną spacją po dwukropku - dzięki temu użytkownik będzie mógł podać liczbę w tej samej linii i komunikat stanie się czytelniejszy.

Twój kod z moimi poprawkami:

using System;

namespace Zadanie_3._14petle
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Program znajdzie dla ciebie liczby doskonale!");
            Console.WriteLine("Podaj przedział od <1,n>");
            Console.Write("Podaj N: ");

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

            for (int i = 1; i <= n; i++)
            {
                int suma = 0;
                for (int j = 1; j < i; j++)
                    if (i % j == 0)
                        suma = suma + j;
                if (suma == i)
                    Console.WriteLine("Liczba {0} jest liczbą doskonałą", i);
            }
            Console.ReadKey();
        }
    }
}
0

Dziękuje CI

1 użytkowników online, w tym zalogowanych: 0, gości: 1