Horner Rekurencyjnie

0

Proszę o pomoc odnośnie poprawienia kodu bo już sam nie wiem jak go naprawić :/

Z góry bardzo dziękuje...

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

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

        {
            int n;

            Console.WriteLine("Podaj stopień wielomioanu: ");
            n = Convert.ToInt32(Console.ReadLine());

            int[] a = new int[n];

            Console.WriteLine("Podaj wartosc a: ");

            for (int i = 0; i <= n; i++)
            {
                Console.WriteLine("a [" + i);
                a[i] = Convert.ToInt32(Console.ReadLine());
            }

            int x;

            Console.WriteLine("Podaj x:");
            x = Convert.ToInt32(Console.ReadLine());

            int Horner(int i)
                {
                    if (i == 0)
                        return a[0];
                    else
                        return Horner(i - 1) * x + a[i];
                }

            Console.WriteLine("Wynik to:" + Horner);
        }
   
    }
}
0

Od kiedy można deklarować funkcje w funkcji?
Poza tym błędnie wywołujesz funkcję (nie podajesz parametrów).

0

Próbowałem to przerobić z kodu w C++ oryginał wygląda tak:

 
int Horner;
int n;
int *a = new int[n];
int x;


int main()
{
        
        cout <<"Podaj stopień wielomianu: ";
        cin >> n;
        cin.ignore();


        cout << "Podaj wartość a: \n";
        for (int i = 0; i <= n; i++)
        {
           cout <<"a[" <<i<<"] = ";
           cin >> a[i];
           cin.ignore();
        }

        cout <<"Podaj x: ";
        cin >> x;
        cin.ignore();

        cout <<"Wynik to: " << Horner(n);
        
        getchar ();
        return 0;
}

int Horner (int i)
{
        if (i == 0)
           return a[0];
        else 
           return Horner (i - 1) * x + a[i];
}

Starałem się właśnie przerobić ten kod na C#

0

Poprawiłem kod na taki jak w C++ domyślam się że dosłownie taki nie będzie to co umiałem to przerobiłem na C# ale dalej już nie za zbytnio mi idzie...

Prosił bym was o pomoc bo dalej sobie nie radzę...

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

namespace Consola_Horner_Rekurencyjnie
{
    class Program
    {
        int Horner;
        int n;
        int[] a = new int[n];
        int x;

        static void Main(string[] args)

        {
            Console.WriteLine("Podaj stopień wielomioanu: ");
            n = Convert.ToInt32(Console.ReadLine());


            Console.WriteLine("Podaj wartosc a: ");

            for (int i = 0; i <= n; i++)
            {
                Console.WriteLine("a [" + i);
                a[i] = Convert.ToInt32(Console.ReadLine());
            }

            Console.WriteLine("Podaj x:");
            x = Convert.ToInt32(Console.ReadLine());

            Console.WriteLine("Wynik to:" + Horner(n));
        }

        int Horner (int i)
        {
            if (i == 0)
                return a[0];
            else
                return Horner(i - 1) * x + a[i];
        }
    }
}
 
0

Takie błędy mi pokazuje:

Error 2 A field initializer cannot reference the non-static field, method, or property 'Consola_Horner_Rekurencyjnie.Program.n'

Error 5 An object reference is required for the non-static field, method, or property 'Consola_Horner_Rekurencyjnie.Program.a'

Error 8 An object reference is required for the non-static field, method, or property 'Consola_Horner_Rekurencyjnie.Program.Horner(int)'

Error 3 An object reference is required for the non-static field, method, or property 'Consola_Horner_Rekurencyjnie.Program.n'

Error 4 An object reference is required for the non-static field, method, or property 'Consola_Horner_Rekurencyjnie.Program.n'

Error 7 An object reference is required for the non-static field, method, or property 'Consola_Horner_Rekurencyjnie.Program.n'

Error 6 An object reference is required for the non-static field, method, or property 'Consola_Horner_Rekurencyjnie.Program.x'

Error 1 The type 'Consola_Horner_Rekurencyjnie.Program' already contains a definition for 'Horner'

0

To nie łaska wpisać błąd na google? Przecież jasno pisze, że z statycznego main nie masz dostępu do zmiennych instancji klasy. A ostatni błąd to bodajże przez posiadanie pola i funkcji Horner.

0

Poprawiłem trochę ten kod ale pokazuje mi błąd przy instrukcji "if" nie wiem jak to poprawić bo pisze że "i" nie istnieje...

Error 2 Since 'Consola_Horner_Rekurencyjnie.Program.Main(string[])' returns void, a return keyword must not be followed by an object expression
Error 1 The name 'i' does not exist in the current context

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

namespace Consola_Horner_Rekurencyjnie
{
    class Program
    {

        static void Main(string[] args)

        {

            int n;

            Console.WriteLine("Podaj stopień wielomioanu: ");
            n = Convert.ToInt32(Console.ReadLine());

            int[] a = new int[n];

            Console.WriteLine("Podaj wartosc a: ");

            for (int i = 0; i <= n; i++)
            {
                Console.WriteLine("a [" + i);
                a[i] = Convert.ToInt32(Console.ReadLine());
            }

            int x;

            Console.WriteLine("Podaj x:");
            x = Convert.ToInt32(Console.ReadLine());

            int Horner;
         
            if (i == 0)
            {
                return a[0];
            }
            else 
            {
                return Horner = (i - 1) * x + a[i];
            }

            Console.WriteLine("Wynik to:" + Horner);
            Console.ReadLine();
        }
    }
}
 
0

Pytanie czy coś w tym stylu może być ?

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

namespace Consola_Horner_Rekurencyjnie
{
    class Program
    {

        static void Main(string[] args)

        {
            int Horner;
            int x;
            int n;

            Console.WriteLine("Podaj stopień wielomioanu: ");
            n = Convert.ToInt32(Console.ReadLine());

            int[] a = new int[n];

            Console.WriteLine("Podaj wartosc a: ");

            for (int i = 0; i <= n; i++)
            {
                Console.WriteLine("a [" + i);
                a[i] = Convert.ToInt32(Console.ReadLine());

                if (i <= 0)
                {
                    return a[0];
                }
                else
                {
                    return Horner = (i - 1) * x + a[i];
                }
            }            

            Console.WriteLine("Podaj x:");
            x = Convert.ToInt32(Console.ReadLine());    

            Console.WriteLine("Wynik to:" + Horner);
            Console.ReadLine();
        }
    }
}

Tylko jeszcze

 return 

pokazuje mi że jest w formie "Void" i nie może zwrócić wartości wiecie może jak to zmienić ?

Bo jak przerabiam

 static void Main(string[] args) 

na int to już mi się wszystko wywala...

0

Tylko teraz lokalnie nie mam zadeklarowanego "Horner" i "x" próbowałem to przenieść w różne miejsca w kodzie i nic nie pomaga :/

2

w C# też są lambdy, ale już się tak wygodnie tego zrobić nie da.

Func<int, int> horner = null;
horner = i => i == 0 ? a[0] : horner(i - 1) * x + a[i];
0

Poprawiłem kod źródłowy, C# nie pokazuje żadnych błędów...

Ale wynik niestety nie jest taki jak się spodziewałem, po tekście "Wynik to: " pokazuje następujący tekst "System.Func '2[System.Int32,System.Int32]

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

namespace Consola_Horner_Rekurencyjnie
{
    class Program
    {

        static void Main(string[] args)

        {
                        
            int n;

            Console.WriteLine("Podaj stopień wielomioanu: ");
            n = Convert.ToInt32(Console.ReadLine());

            int[] a = new int[++n];

            Console.WriteLine("Podaj wartosc a: ");
           
            for (int i = 0; i < n; i++)
            {
                Console.WriteLine("a [" + i + "] = ");
                a[i] = Convert.ToInt32(Console.ReadLine());
            }
            
            int x;

            Console.WriteLine("Podaj x:");
            x = Convert.ToInt32(Console.ReadLine());
            

            Func<int, int> Horner = null;
            Horner = (i) => (i == 0) ? a[0] : Horner(i - 1) * x + a[i];              

            Console.WriteLine("Wynik to:" + Horner);
            Console.ReadLine();
        }
    }
}
0

Rev po jakiego diabła dałeś mu Func, jak on nie wie jak go wykorzystać?

mcshow - w twoim przypadku zamiast samo Horner, powinno być Horner(x) w Console.WriteLine. Ale zaraz jak to poprawisz, masz się wziąć za książkę z .NET. Takie błędy jakie tutaj popełniasz mógłbyś zaraz rozwiązać, gdybyś miał choć elementarne podstawy.

0

Mam jeszcze jedno pytanie gdyż mam już takową postać kodu która czysto teoretycznie powinna zwracać odpowiedni wynik ale...

wyskakuje mi błąd że zmienna "x" jest już wcześniej zadeklarowana (co musiałem uczynić żeby uzyskać ją od użytkownika) a wymieniona w "Horner" na inne znaczenie...

jak zmieniam "x" w "Horner" na np. "y" to nie pokazuje mi żadnych błędów ale po uruchomieniu program mi się wywala całkowicie ( i w sumie to rozumiem bo wymagam od użytkownika podania wartości X i na niej ma być wykonywane działanie a nie na "y")

Jak zmienić nazwę dla "x" tak żeby nie wyskakiwał błąd...?

 
Func<int, int, int> Horner = null;
Horner = (i, x) => (i == 0) ? a[0] : Horner(i - 1, x) * x + a[i];

int wynik = Horner(n, x);
0

Po to mądrzy ludzie wymyślili domknięcia, żebyś mógł w tej funkcji odwołać się do x bez przekazywania go w dodatkowym argumencie. Zostaw kod w takiej postaci, w której ja go napisałem.

0

To czysto teoretycznie powinno być dobrze... a program powinien się kompilować...

 
        {
            
            int n;

            Console.WriteLine("Podaj stopień wielomioanu: ");
            n = Convert.ToInt32(Console.ReadLine());

            int[] a = new int[++n];

            Console.WriteLine("Podaj wartosc a: ");

            for (int i = 0; i < n; i++)
            {
                Console.WriteLine("a [" + i + "] = ");
                a[i] = Convert.ToInt32(Console.ReadLine());
            }

            int x;

            Console.WriteLine("Podaj x:");
            x = Convert.ToInt32(Console.ReadLine());

            Func<int, int, int> Horner = null;
            Horner = (i, x) => (i == 0) ? a[0] : Horner(i - 1, x) * x + a[i];

            int wynik = Horner(n, x);

            Console.WriteLine("Wynik to:" + wynik);
            Console.ReadLine();
        }
    }
}
0
Horner = (i, x) => (i == 0) ? a[0] : Horner(i - 1, x) * x + a[i];

Nie możesz tutaj użyć nazwy x - używasz już takiej zmiennej w programie.
Zmień x na np. z.
Następnym razem podaj, gdzie i jaki wywala ci błąd.

0

Żadna zmiana x na z czy cokolwiek innego. Na tym polega domknięcie w tym miejscu, że w funkcji lambda możesz sobie wykorzystać to x, które zadeklarowałeś wcześniej, po za tą faktyczną funkcją. Nie trzeba go w argumencie przekazywać.

Drugi błąd to zmiana wymiaru wielomianu - w pewnym momencie zwiększasz go o 1 i taki nieprawidłowy wymiar przekazujesz do funkcji.

Zostaw funkcję taką, którą ci podałem, nic w niej nie zmieniaj. Tylko to n popraw.

0

@mcshow Tak z ciekawości, do czego potrzebujesz ten program?

0

Wielomian zwiększam o jeden bo ma być od 0 do n... A w podanym poniżej miejscu zmniejszam go i tylko dlatego bo inaczej kod się nie kompiluje:

 
for (int i = 0; i < n; i++)
            {
                Console.WriteLine("a [" + i + "] = ");
                a[i] = Convert.ToInt32(Console.ReadLine());
            }

Więc wydaje mi się że mam dobrze...

@Rev co do twojego kodu który podałeś to wszystko ok, nie wyskakuje żaden błąd ale dostaje złe wyniki...

 
Func<int, int> horner = null;
horner = i => i == 0 ? a[0] : horner(i - 1) * x + a[i];
0

Dobra poddaje się... :/

Pytanie czy da się ten kod:

 
Func<int, int> horner = null;
            horner = i => i == 0 ? a[0] : horner(i - 1) * x + a[i];

przedstawić w jakiejś prostszej postaci jak np. ???

 
int w;

            w = a[0];
            for (int i = 1; i < n; i++)
            {
                w = w * x + a[i];
            }
0

Co myślicie o tym... Ma to rację bytu ?

 
public double Horner(double[] a, double x)
{
 	int n = a.lenght;
	double wynik = a[n];
	for (int i = n-1; i >= 0;i--)
	{
		wynik = wynik * x + a[i];
	}
	return wynik;
}
0
Rev napisał(a)

Ja to uznaje za plus, z reszta, gdyby tak nie bylo nigdy domkniecia by nie byly feature jezyka

Ale pytanie było o funkcje lokalne. W C można bezpośrednio:

int foo()
{
    int a = 3;

    int abc(int b, int c)
    {
        return a+b+c;
    }

    return abc(4,7);
}

w C++ można z powodzeniem zastosować wyrażenie lambda, jest tylko „trudniejsza” składnia — ale przecież C++ lubi wszystko utrudniać:

int foo()
{
    int a = 3;

    auto abc = [&](int b, int c) -> int
    {
        return a+b+c;
    };

    return abc(4,7);
}

Co ciekawe, kolejnością poszczególnych elementów zbliża to C++ do Pascala (typ zwracany funkcji na końcu za parametrami).

w C# bezpośrednim odpowiednikiem byłoby:

static int foo()
{
    int a = 3;

    var abc = (int b, int c) =>
    {
        return a+b+c;
    };

    return abc(4,7);
}

ale raz że nie można podać jawnie zwracanego typu, to jeszcze kompilator nie potrafi się „domyśleć” jaki ma być typ zmiennej abc (a w C++ jakoś może...)

Nic nie da składnia ze słowem delegate:

static int foo()
{
    int a = 3;

    var abc = delegate (int b, int c)
    {
        return a+b+c;
    };

    return abc(4,7);
}

To samo; nie może być var.

Trzeba podać jawnie typ:

static int foo()
{
    int a = 3;

    System.Func<int,int,int> abc = (int b, int c) =>
    {
        return a+b+c;
    };

    return abc(4,7);
}

ale teraz dwukrotnie powtarzamy typy parametrów. możemy jedne wyrzucić:

static int foo()
{
    int a = 3;

    System.Func<int,int,int> abc = (b, c) =>
    {
        return a+b+c;
    };

    return abc(4,7);
}

I to jest jak w twoim przykładzie. Niestety, typy parametrów i ich nazwy są rozdzielone, i nie widać który jest który (a gdyby parametrów było więcej?). Przypominam, że chodzi nam po prostu o symulowanie funkcji lokalnej.
Na dodatek nie jest oczywiste, które dwa z trzech intów to typy parametrów, a który to typ zwracany. Przyznam że nawet nie wiem, zawsze muszę to w helpie sprawdzać.

Wniosek 1: lambdy w C# do udawania funkcji lokalnych się nie nadają.
To działa, ale składnia jest do kitu, gorsza niż C++.

Wniosek 2: C++ i C# powinny po prostu pozwalać na funkcje lokalne, choćby tylko jako lukier składniowy na odpowiednie lambdy. Nie widzę przeciwskazań, skoro i tak można to osiągnąć na około.

0

I tu też moje pytanie jak by można najprościej przedstawić kod z C++

 
int Horner (int i)
{
        if (i == 0)
           return a[0];
        else 
           return Horner (i - 1) * x + a[i];
}

w C#... bez domknięć, Func itp... ? Musi być taki jak wyżej podany bo chcę pokazać różnicę w sposobie liczenia między Intracyjnym a Rekurencyjnym...

0

W C można bezpośrednio

W C nie ma funkcji zagnieżdżonych!

0
Azarien napisał(a)

Na dodatek nie jest oczywiste, które dwa z trzech intów to typy parametrów, a który to typ zwracany. Przyznam że nawet nie wiem, zawsze muszę to w helpie sprawdzać.

OSTATNI to typ zwracany. To jest ekstremalnie łatwe do zapamiętania.

Wniosek 1: lambdy w C# do udawania funkcji lokalnych się nie nadają.
To działa, ale składnia jest do kitu, gorsza niż C++.

Nadają się i to całkiem dobrze. Może i pisanie Func<T1, T2, ..., TOut> może nie jest do końca wygodne, za to od razu widać, co funkcja przyjmuje i co zwraca. Szczerze mówiąc, wolę chyba taką formę zapisu niż miałoby to być var, które nie daje żadnej informacji o typach podczas czytania kodu.

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