Obiekt Random - dziwne zachowanie

0

Witam

Mam klasy:

class LiczbaZespolona
    {
        private double czescRe;
        public double CzescRe
        {
            get
            {
                return czescRe;
            }
            set
            {
                czescRe = value;
            }
        }
        private double czescIm;
        public double CzescIm
        {
            get
            {
                return czescIm;
            }
            set
            {
                czescIm = value;
            }
        }
        public LiczbaZespolona(double re, double im)
        {
            this.czescRe = re;
            this.czescIm = im;
        } 
class TablicaZespolonych
    {
        private List<LiczbaZespolona> listaLiczbZespolonych = new List<LiczbaZespolona>();
        private Random rnd = new Random();

        public TablicaZespolonych()
        {
            this.WypelnijTablice();
        }

        private void WypelnijTablice()
        {
            int rozmiar = rnd.Next(10, 20);
            for (int i = 0; i < rozmiar; i++)
            {
                double a = rnd.Next(-100, 100);
                double b = rnd.Next(-100, 100);
                listaLiczbZespolonych.Add(new LiczbaZespolona(a, b));
            }
        } 

I testuje je tak:

 
            TablicaZespolonych tab1 = new TablicaZespolonych(); 
            Console.WriteLine("Wypisanie zawartosci tablicy 1");
            tab1.WypiszTabliceNaKonsoli();
            
            

            TablicaZespolonych tab2 = new TablicaZespolonych();
            Console.WriteLine("Wypisanie zawartosci tablicy 2");
            tab2.WypiszTabliceNaKonsoli();

            //tab1.DodajTablice(tab2);
            //Console.WriteLine("Wypisanie sumy w tablicy 1");
            //tab1.WypiszTabliceNaKonsoli();

            Console.ReadLine();

W takiej postaci jak to teraz jest dziala ok, Obiekty tab1 i tab2 przechowuja rózne liczby zespolone i maja rozne wymiary. Ale jezeli odkomentarzuje zakomentarzonwana czesc z testu, tab1 i tab2 maja identyczne wartosci i wymiary a ich suma jest równa tab1+tab2. Skad to sie bierze?

podaje jeszcze metode dodawania tablicy z klasy TablicaZespolonych:

        public void DodajTablice(TablicaZespolonych t2)
        {
            for(int i = 0; i < t2.listaLiczbZespolonych.Count; i++)
            {
                this.listaLiczbZespolonych[i].Dodaj(t2.listaLiczbZespolonych[i]);
            }
            if(t2.listaLiczbZespolonych.Count > this.listaLiczbZespolonych.Count)
            {
                for(int i = this.listaLiczbZespolonych.Count; i < t2.listaLiczbZespolonych.Count; i++)
                {
                    listaLiczbZespolonych.Add(t2.listaLiczbZespolonych[i]);
                }
            }
        } 

Identyczny blad jest wtedy gdy w programie testujacym zrobie tak:

            TablicaZespolonych tab1 = new TablicaZespolonych();
            TablicaZespolonych tab2 = new TablicaZespolonych();



            Console.WriteLine("Wypisanie zawartosci tablicy 1");
            tab1.WypiszTabliceNaKonsoli();  
            Console.WriteLine("Wypisanie zawartosci tablicy 2");
            tab2.WypiszTabliceNaKonsoli();

            //tab1.DodajTablice(tab2);
            //Console.WriteLine("Wypisanie sumy w tablicy 1");
            //tab1.WypiszTabliceNaKonsoli();

            Console.ReadLine(); 

Teraz znow obiekty tab1 i tab2 maja takie same wymiary i takie same wartosci.

Na pierwszy rzut oka random dziala dobrze i losuje faktycznie losowo liczby, staram sie znaleŹĆ gdzie przez referencje mieszam miedzy tab1 a tab2 ale tez tego nie widze. Jakby ktos mogl to prosilbym o pomoc w znalezieniu przyczyny takiego zachowania programu.

1

Źle tworzysz obiekt Random. Utwórz go jako obiekt statyczny i przekazuj do swoich klas w ich konstruktorach. Jak tworzysz dynamicznie kilka obiektów Random to może się zdarzyć, że wylosują one te same wartości, bo nie są to prawdziwe generatory losowych liczb tylko pseudogeneratory - algorytmy, które wyliczają liczby.

0

public double CzescRe
{
get
{
return czescRe;
}
set
{
czescRe = value;
}
ech… sztandarowy przykład na klasę (a w tym przypadku lepiej nawet strukturę), gdzie uzasadnione są pola publiczne.

To jest liczba zespolona.Twór czysto matematyczny. Nigdy w nim nie powinny znaleźć się inne pola niż część rzeczywista i urojona, nie powinien się wykonywać też dodatkowy żaden kod podczas przypisywania czy pobierania wartości (podobnie jak ze zwykłym double-m czy int-em).

struct LiczbaZespolona
{
  public double czescRe, czescIm;
  /* konstruktor, metody, operatory, ale żadne dodatkowe pola */
}

użycie właściwości, tym bardziej z jawnymi akcesorami, tylko kusi żeby coś tam może jeszcze dodać…

0
maszynaz napisał(a)

Źle tworzysz obiekt Random. Utwórz go jako obiekt statyczny i przekazuj do swoich klas w ich konstruktorach. Jak tworzysz dynamicznie kilka obiektów Random to może się zdarzyć, że wylosują one te same wartości, bo nie są to prawdziwe generatory losowych liczb tylko pseudogeneratory - algorytmy, które wyliczają liczby.

Pomogło to:

 
class TablicaZespolonych
    {
        private List<LiczbaZespolona> listaLiczbZespolonych = new List<LiczbaZespolona>();
        static Random rnd = new Random();

        public TablicaZespolonych()
        {
            this.WypelnijTablice(rnd);
        }

        private void WypelnijTablice(Random rnd)
        {
            int rozmiar = rnd.Next(10, 20);
            for (int i = 0; i < rozmiar; i++)
            {
                double a = rnd.Next(-100, 100);
                double b = rnd.Next(-100, 100);
                listaLiczbZespolonych.Add(new LiczbaZespolona(a, b));
            }
        }
}
            TablicaZespolonych tab1 = new TablicaZespolonych();
            TablicaZespolonych tab2 = new TablicaZespolonych();

            Console.WriteLine("Wypisanie zawartosci tablicy 1");
            tab1.WypiszTabliceNaKonsoli();  
            Console.WriteLine("Wypisanie zawartosci tablicy 2");
            tab2.WypiszTabliceNaKonsoli();

            tab1.DodajTablice(tab2);
            Console.WriteLine("Wypisanie sumy w tablicy 1");
            tab1.WypiszTabliceNaKonsoli();

            Console.ReadLine(); 

Ale i takie podejscie pomogło:

 
    class TablicaZespolonych
    {
        private List<LiczbaZespolona> listaLiczbZespolonych = new List<LiczbaZespolona>();

        public TablicaZespolonych(Random rnd)
        {
            this.WypelnijTablice(rnd);
        }

        private void WypelnijTablice(Random rnd)
        {
            int rozmiar = rnd.Next(10, 20);
            for (int i = 0; i < rozmiar; i++)
            {
                double a = rnd.Next(-100, 100);
                double b = rnd.Next(-100, 100);
                listaLiczbZespolonych.Add(new LiczbaZespolona(a, b));
            }
        }
}
            Random rnd = new Random();

            TablicaZespolonych tab1 = new TablicaZespolonych(rnd);
            TablicaZespolonych tab2 = new TablicaZespolonych(rnd);

            Console.WriteLine("Wypisanie zawartosci tablicy 1");
            tab1.WypiszTabliceNaKonsoli();  
            Console.WriteLine("Wypisanie zawartosci tablicy 2");
            tab2.WypiszTabliceNaKonsoli();

            tab1.DodajTablice(tab2);
            Console.WriteLine("Wypisanie sumy w tablicy 1");
            tab1.WypiszTabliceNaKonsoli();

            Console.ReadLine(); 

Rozumiem że miałeś na mysli to drugie rozwiaznie, czy pierwsze jest z jakiegos wzgledu nie niewlasciwe?

0
Azarien napisał(a)

ech… sztandarowy przykład na klasę (a w tym przypadku lepiej nawet strukturę), gdzie uzasadnione są pola publiczne.

A co uzasadnia ten gwałt na konwencji, ograniczanie sobie możliwości databindingu i utrudnianie refleksji? I nie zapominajmy, że jeśli dojdziemy do wniosku, że jednak potrzebujemy właściwości, to musimy przerobić CAŁY kod, który z tego pola korzysta.

0

Witam

Chce sie jeszcze upewnic.

Niezbyt mi pasuje wyciaganie obiektu Random calkowicie z klasy i przekazywanie go przez konstruktor do obiektu klasy TablicaZespolonych w momencie tworzenia go.
Czy oznaczenie pola Typu Random w klasie TablicaZespolonych, jako static nie spelni warunku ze to pole typu Random jest jednym wspolnym dla każdego nowopowolanego obiektu tego typu?
W czasie moich testow wychodzi ze jest ok, nie mam jakis dziwnych zachowan z losowaniem jak na samym poczatku.

0

Czy oznaczenie pola Typu Random w klasie TablicaZespolonych, jako static nie spelni warunku ze to pole typu Random jest jednym wspolnym dla każdego nowopowolanego obiektu tego typu?
Prawie spełni, tj. może się zdarzyć, że w jakimś innym typie będziesz też miał Randoma, który zainicjowany w tym samym momencie będzie generował tę samą sekwencję. Niedawno na tym forum ktoś miał dokładnie taki problem.

Jeśli interesuje cię tylko ta jedna klasa, to możesz tak zrobić.

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