PDA

Zobacz pełną wersję : rozmiar tablicy w c++



macol
11-01-07, 12:19
Czy jest moźliwość zmiany rozmiaru tablicy w c++?
Ale bez źadnych skomplikowanych wskaźnikłw, skomplikowanych obiektłw czy innych dodatkowych bibliotek... tzn. jak najprościej, jak najmniej kodu...

RRybak
11-01-07, 22:41
Nie czaję pytania tak do końca. Podejrzewam, źe masz zadeklarowane:
int tablica[50]

i chciałbyś gdzieś w kodzie uzyskać tablica[100]=jakas_wartosc?

Jeśli o tym młwimy, to "bez skomplikowanych wskaźnikłw" się nie da. Moźesz na upartego zadeklarować jakąś duźą tablicę ZA tą ktłrej potrzebujesz, czyli np.:
int tablica[50];
int rezerwa[100];

W zaleźności od kompilatora i stopnia optymalizacji w większości wypadkłw da się wjechać na tablica[100], jednak takie zagrania często kończą się błędem naruszenia pamięci i nie są zalecane :) Poza tym czemu nie zadeklarujesz od początku większej?

Jak pisze na większości stron:


C++ Array Disadvantages:
* Fixed size data. If the number of elements stored are less than the maximum size, then the rest of the memory space goes waste.
* If the number of elements to be stored are more than the maximum size, the array cannot accommodate those new values.
Jeśli chcesz dynamicznie zmieniać rozmiar - twłrz ją dynamicznie. To naprawdę tylko na początku wydaje się straszne ;)

macol
11-01-07, 23:52
no powiedzmy źe problem nieaktualny... mam nadzieje..

jeszcze jedno pytanko...

Czy jest moźliwość przekazać tablice dwuwymiarową jako parametr do funkcji? Oczywiście nieznając rozmiarłw tablicy, tzn wymiary jej to int gx, int gy :D
Jak zadeklarować funkcje przyjmującą taką tablice za parametr?

r-mi
12-01-07, 05:22
Moe by tak, ale to nie jest szeroko obsugiwany standard.
func(int x, int y, int tab[a][b])

Zwykle tylko rozmiar jednego wymiaru moe by nieznany
func(int tab[][10])
func(int (*tab)[10])

albo przekazujesz wskanik i pozycj w tablicy liczysz rcznie
func (int *t, int wierszy, int kolumn)
{
int element_x_y = *(t + (x + y * kolumn));
}


Jeli o tym mwimy, to "bez skomplikowanych wskanikw" si nie da
Ale to nic skomplikowanego. Po prostu bierzesz blok pamici i robisz realloc, tylko, e zwykle oznacza to po prostu alokacj nowego bloku pamici i skopiowanie w to miejsce zawartoci poprzedniego bloku (bardzo nieefektywne). Albo po prostu uywasz vector z STL'a - jeszcze bardziej nieefektywne :)


Moesz na upartego zadeklarowa jak du tablic ZA t ktrej potrzebujesz, czyli np.:
Pomijajc zagmatwanie i totalny brak sensu takiego rozwizania - bo taka "rezerwa" zuywa pami obojtnie, czy jest uywana, czy nie wic rwnie dobrze moesz zadeklarowa zmienn 150 elementow. Z reszt to bdzie nawet szybciej, kompilator wygeneruje mniej kodu.


W zalenoci od kompilatora i stopnia optymalizacji w wikszoci wypadkw da si wjecha na tablica[100]
RRybak nawet tego nie pisz. Wiesz z czego sie bierze 90% atakw na wspczesny soft? Z tego, e kto zapomnia sprawdzi rozmiar danych wejciowych i mona tak sobie "wjecha" za tablic z reszt wanie przez moliwo takiego wjedania wprowadzono randomizacj adresu powrotu w nowych jdrach linuxa i od tego czasu nikt na prawd nie wie jak si taki "wyjechany" :D kod zachowa.


czsto kocz si bdem naruszenia pamici i nie s zalecane
Kocz si bdem naruszenia pamici tylko kiedy wychodzimy poza stos, a zawsze kocz si uszkodzeniem obszaru danych programu. Zwykle jeli kompilujemy pod release a nie debug nawet nie mona tego zauway (po prostu jakie dane aplikacji zostan uszkodzone). Std rozmaite narzdzia do testowania bdw pamici. Bdem naruszenia pamici (od razu) koczy si wyjcie poza pami dynamicznie alokowan ale nie na stosie jak w tym wypadku.

Np visual c dodaje po kadym zarezerwowanym bloku przy kompilacji pod debug obszar pusty - eby stwierdzi czy programista nie wyszed poza obszar tablicy. Taki program z "wyjciami" bdzie dziaa wietnie, do chwili kiedy nie skompiluje si go bez uycia mega wolnych, mega duych i mega pamicioernych bibliotek w wersji dla debuggera.


Poza tym czemu nie zadeklarujesz od pocztku wikszej?
Bo tak nie powinno si robi. Co by byo, gdyby windows alokowa wszystko "od pocztku wiksze"? Zamiast tylko 512 MB potrzebowalibymy 512TB ram, eby zagra w sapera ;)

RRybak
12-01-07, 05:58
Wjechanie na danych na pamięć programu i vice versa JEST naruszeniem ochrony pamięci :) W zaleźności od warunkłw (vide XP i Core2Duo) prłba takiego czegoś kończy się ubiciem programu - oczywiście przy oznaczeniu "to jest blok programu, a to blok pamięci" :)
Napisałem, źe nie zalecam takiego wyjeźdźania, ale jak komuś zaleźy, to co się będę chował :lol: Uprzedziłem w końcu, źe to niebezpieczne ;)
Co do jeszcze większej szczegłłowości, zauwaź źe większość parametrłw jest przekazywanych przez stos, i głłwnie na nich następuje "wyjazd", więc tak czy inaczej wychodzi na nasze :)


(..)czy nie więc rłwnie dobrze moźesz zadeklarować zmienną 150 elementową. Z resztą to będzie nawet szybciej, kompilator wygeneruje mniej kodu.
(..)
Bo tak nie powinno się robić. Co by było, gdyby windows alokował wszystko "od początku większe"?
No sam się zamotałeś, ale co tam:) Szczerze młwiąc, to nie jestem przekonany tak do końca, czy windows właśnie w ten sposłb nie postępuje ;-)
Ogłlnie praktyką powinno być, źe jeśli nie znamy rozmiaru tablicy to korzystamy z dynamicznego przydziału i tyle.

Co do przekazywania tablic jako parametr, to źycie nauczyło mnie przekazywać je przez wskaźnik i to wydaje się najlepszym rozwiązaniem. Są jakieś tam funkcje virtualizacji, ale przyznam się szczerze, źe wymiękam na etapie dokumentacji - po co się męczyć jak moźna stare kochane *tablica wykorzystać :)

r-mi
12-01-07, 08:45
Wjechanie na danych na pami programu i vice versa JEST naruszeniem ochrony pamici :smile:. oczywicie przy oznaczeniu "to jest blok programu, a to blok pamici"
Gupoty gadasz i to konkretne :)
Pamitasz kod w stylu char[] = '\x90\x77\x10\x30'; Co to jest? Kod assemblera umieszczany w pamici danych. Zgodnie z tym co piszesz wykonanie takiego kodu powinno wywoa bd ochrony. Dlaczego tak si nie dzieje?

W architekturze CISC oglnie i w 386 szczeglnie nie ma rozgraniczenia na pami danych i kodu (wanie dlatego moliwe s ataki typu buffer overflow - zapisujesz kod do pamici danych). Nawet gdyby takie rozgraniczenie byo - stos to pami danych a nie pami programu (kodu), tak samo jak lista, kolejka, drzewo, czy jakakolwiek inna struktura danych.

System operacyjny nawet nie zauway e wjechae na obszar stosu nalecy do innej zmiennej - bo to jest jeden i ten sam obszar dla kadej zmiennej statycznej zadeklarowanej w programie. Inaczej: kada zmienna statyczna korzysta z wycinka tego obszaru. Pisania poza tablic nie mona wykry, chyba e spompilujesz pod debug lub / i kompilator generuje kod w ktrym wczone jest sprawdzanie granic tablic (co spowalnia wydajno). Moe masz w tym wypadku wyjtek - ale generuje go kod doczany przez kompilator a nie system operacyjny. Chyba za bardzo nie wiesz, co masz zaznaczone w opcjach kompilacji.

Przykadowy wygld stosu:
BYTE* stack = malloc(40000);
char* t[] = (char[20]*) stack;
char* u[] = (char[19]*) (stack+20);
Jak pisanie poza t, na u ma powodowa jakiekolwiek naruszenie pamici, skoro zostao jeszcze 39980 bajtw a u ma bajtw 19? Obszar pamici jest cigy. Po prostu zapiszesz na u i nic nie stoi na przeszkodzie, eby zadeklarowa sobie
char* Y[] = (char[2000]*) (stack+5);

Ochrona pamici polega na tym, e program moe pisa w dowolnym obszarze pamici zarezerwowanym przez siebie. I nie wane jak sobie zrzutujesz wskanik, czy jak nazwiesz zmienn.


W zalenoci od warunkw (vide XP i Core2Duo)
A co maj te niby "warunki" do dziaania programu? Gdyby byo 50 rdzeni to mylisz, e dziaaby inaczej. Jeden wtek wykonuje si na 1 rdzeniu a nie na 2 czy 50. Z reszt w "zalenoci od warunkw" program dziaa zupenie tak samo. Wirtualn przestrze adresow 4GB i ochron pamici masz dla wszystkich win 32 bitowych. System ma tylko dopilnowa, eby program dosta swoj cz procesora i nie mg czyta / pisa z przestrzeni adresowej innych aplikacji a organizacja stosu czy zarzdzanie przydzielon pamici to wewntrzna sprawa kadej aplikacji, w ktr OS nie ingeruje.


No sam si zamotae, ale co tam
Po prostu nie wiesz czym rni si alokacja statyczna od dynamicznej. Wic przykad:



void f(char* dane, int dlugosc)
{
char zmienna[50];
if (dlugosc> 50)
{
char pomocnicza[100];
// skopiuj nadmiarowe do pomocniczej
}

// jaki kod
// ...

wyswietl(&zmienna[0]);
if (dlugosc> 50)
{
wyswietl(&pomocnicza[0]); // DUPA! ;)
}
}


Wic jak chcesz si dobra do tej tablicy danych nadmiarowych, ktra zostanie wyrzucona zaraz potem - jak program wyjdzie z bloku IF? Bdziesz po prostu musia zadeklarowa to tak:



char zmienna[50];
char pomocnicza[100];

A jaki w tym sens i czym si to rni od deklaracji zmienna[150]? Tym e nie wprowadza niepotrzebnych komplikacji, zajmuje mniej czasu i miejsca w pamici. Nie da si zrobi dynamicznego przydziau pamici na zmiennych statycznych. Przecie to nawet brzmi miesznie!


Szczerze mwic, to nie jestem przekonany tak do koca, czy windows wanie w ten sposb nie postpuje :wink:
Chyba zwariowae ju do koca ;) Co by nie mwi o tym systemie, nie ma najmniejszej opcji, pierwsze pieko zamarznie, ni kto zastosowaby tak durny sposb alokacji zmiennych. Nawet znany z gupawych pomysw microsoft. Bo tego si po prostu nie da zrobi.


Oglnie praktyk powinno by, e jeli nie znamy rozmiaru tablicy to korzystamy z dynamicznego przydziau i tyle.
No w kocu jakie zdanie z sensem.


Co do przekazywania tablic jako parametr, to ycie nauczyo mnie przekazywa je przez wskanik i to wydaje si najlepszym rozwizaniem.
Nie zawsze. Przekazujc przez referencje nie tracisz informacji o typie i moesz wywoa sizeof zamiast przekazywa rozmiar oddzielnie.

RRybak
12-01-07, 09:58
Oj no, ale źeś się wdał w polemikę :P Zbyt dosłownie bierzesz sobie do serca moje satyryczne teksty :) Gwarantuję Ci, źe architekturę x86 i programowanie znam aź nadto, no ale niech Ci będzie - do części się ustosunkuję, postaram się najbardziej fachowo, źeby przemłwiło ;)

1. Tak, wiem do czego słuźy Range Checking - obsługa wyjątkłw, co z tego źe programowa - pilnuje źeby nie wyjechać poza dopuszczalny obszar i raczej opiera się na zdefiniowanych zakresach niź rozdzielaniu kodu od danych

2.
Jak pisanie poza t, na u ma powodować jakiekolwiek naruszenie pamięc
..aleź ja nigdzie nie napisałem, źe pisanie po zmiennych obok siebie spowoduje naruszenie jakiejś pamięci :) Zauwaź, źe w pierwszym poście właśnie takie, o irionio, "rozwiązanie" zaproponowałem :P

3.
A co mają te niby "warunki" do działania programu
Ano witamy w erze Data Execution Prevention. Opisane na przykład tu:
http://www.microsoft.com/technet/prodtechnol/winxppro/pl/maintain/sp2mempr.mspx


Wirtualną przestrzeń adresową 4GB i ochronę pamięci masz dla wszystkich win 32 bitowych. System ma tylko dopilnować, źeby program dostał swoją część procesora i nie młgł czytać / pisać z przestrzeni adresowej innych aplikacji a organizacja stosu czy zarządzanie przydzieloną pamięcią to wewnętrzna sprawa kaźdej aplikacji, w ktłrą OS nie ingeruje.
Przestrzeń wirtualna to w tym przypadku ZUPEŁNIE inna sprawa. Swoją drogą wirtualizacja została wprowadzona juź w procesorach 80386, ktłrym daleko było do "win 32 bitowych". Chociaź teoretycznie powinny były dać radę. Tak czy inaczej system w tym przypadku INGERUJE, chociaź wspierany sprzętowo.

Z ciekawostek - oprłcz technologi typu DEP istnieje juź moźliwość odpalenia dwłch systemłw operacyjnych na raz i niekoniecznie wiąźe się to z "wirtualną przestrzenią adresową". Przyznam jednak szczerze, źe akurat tego jeszcze nie widziałem w akcji (pomijając VM).

4.
Po prostu nie wiesz czym rłźni się alokacja statyczna od dynamicznej.
Patrz "wstęp" :)

Twoje:

Nie da się zrobić dynamicznego przydziału pamięci na zmiennych statycznych.
Wcześniejsze moje:

Jeśli chcesz dynamicznie zmieniać rozmiar - twłrz ją dynamicznie.

I znowu Twoje:

czym się to rłźni od deklaracji zmienna[150]? Tym źe nie wprowadza niepotrzebnych komplikacji,
Przecieź ja mu od początku młwiłem, źeby od razu większe zadeklarować, przykład 50/100 był satyrycznym, działającym, ale jakby nie było - satyrycznym rozwiązaniem :P Nie rozumiem po co w ogłle się przyczepiłeś do tych paragrafłw:P Patrz na całość wątku, a nie zdaniami - wyciąganie z kontekstu rłźnie się kończy :P

5. Co do Windowsa - no kurde niestety nie ma na forum znacznikłw IronyON i IronyOFF. Nie trawię M$ i nic na to nie poradzę, nie traktuj źycia tak śmiertelnie powaźnie - i tak z niego źywy nie wyjdziesz ;)

6. Przekazywanie przez referencję, czy przez wskaźnik - nigdzie nie ująłem, źe to jest jedyna słuszna metoda. Zwrłć uwagę na "źycie nauczyło mnie", co oznacza, źe W MOIM przypadku i w projektach, ktłre JA tworzę lepiej sprawdza się "wskaźnik" :)

Chłopak chciał wiedzieć "czy się da", a my z tego robimy kurs sprzętowo-programistyczny - nie ma sprawy, ale to nie w tym wątku. Moźemy załoźyć szkłłkę i tam będziemy dyskutować o "za i przeciw" rozwiązań :)
Zrelaksuj się - mamy nowy rok ;) :piwko:

macol
12-01-07, 12:43
Moźe zacznę od tego, źe na dzień dzisiejszy młj kontakt z C++ trwa juź 3 dni... w związku z tym wskaźniki są jeszcze dla mnie magią, ktłrej uźywać nie potrafię, więc jak mam ich juź uźyć, to potrzebuje opis tak prosty, źeby przedszkolak zrozumiał... :D


RRybak nawet tego nie pisz. Wiesz z czego sie bierze 90% atakłw na wspłłczesny soft?
Lać ataki na soft... to co "pisze" nigdy nie będzie uźywane produkcyjnie, to parę zadań logicznych ktłre muszę zrobić do końca miesiąca, i tyle, a w VB.NET/c# tego pisać nie mogę...



albo przekazujesz wskaźnik i pozycję w tablicy liczysz ręcznie
func (int *t, int wierszy, int kolumn)
{
int element_x_y = *(t + (x + y * kolumn));
}i po tym mogę w funkcji korzystać z tablicy, ktłra będzie się nazywała...?
I jak wywołać tą funkcje, tzn jak zapisać pierwszy parametr? wystarczy
func(tab[][], x, y) ?

r-mi
12-01-07, 23:49
i po tym mogę w funkcji korzystać z tablicy, ktłra będzie się nazywała...?
I jak wywołać tą funkcje, tzn jak zapisać pierwszy parametr? wystarczy
void func(char* tab, int szer, int wys)
{

for (int i=0; i<szer; i++)
for(int ii=0; ii< wys; ii++)
{
char element_ii = *(tab + i + szer*ii);

}
}


Zbyt dosłownie bierzesz sobie do serca moje satyryczne teksty
LOL Satyryczne teksty o wskaźnikach i alokacji pamięci. Sorry, ale niezbyt do tego przywykłem :P

bombellb
20-01-07, 11:52
najlepiej jest alkować tablice dynamicznie, jest to bardzo proste. Korzystasz ze wskaźnikłw ale tylko przy inicjalizacji, potem juź działasz tak jak na zwykłej statycznej tablicy. Dla zwykłaj tablicy jedno wymiarowwej z n elementami robisz to tak:
double *t=new double[n], dla tablicy dwu wymiarowej czyli dla macierzy robi się to troszkę trudniej ale jak będziesz potrzebował to daj znać

macol
20-01-07, 12:12
moźesz śmiało pisać, bo zadanko, w ktłrym będę potrzebował tablice dwuwymiarowe jeszcze przede mną, a na razie bez rekurencji(czyli przekazania do funkcji tej dwuwymiarowej tablicy) rozwiązania nie widze..

Alpha
30-01-07, 11:42
bez rekurencji(czyli przekazania do funkcji tej dwuwymiarowej tablicy)
Kolego.
To nie jest rekurencja!
Rekurencja (bezpośrednia) to wywołanie podprogramu w jego ciele.

macol
30-01-07, 14:53
To nie jest rekurencja!
Rekurencja (bezpośrednia) to wywołanie podprogramu w jego ciele.
No i??
Jak program ma mieć deklaracji coś podobnego do:
void main(char tablica[][])
Do szlem do etapu na ktłrym wiem źe źaden wymiar nigdy nie będzie musiał być większy niź 100, i deklaruje
void main(char tablica[100][100]), co mi zupełnie wystarcza...

Alpha
30-01-07, 15:47
Jak program ma mieć deklaracji coś podobnego do:
void main(char tablica[][])
Do szlem do etapu na ktłrym wiem źe źaden wymiar nigdy nie będzie musiał być większy niź 100, i deklaruje
void main(char tablica[100][100]), co mi zupełnie wystarcza...

r-mi 12-01-2007, 06:22 słusznie napisał.
Dokładniej wszystkie za wyjątkiem pierwszego rozmiaru muszą być określone (czyli moźe być tablica elementłw (nie wiadomo ilu), kaźdy element juź o określonym wymiarze).
Tu muszisz przekazywac obiekt zadeklarowany jako 2-wym tablica (zaniedbuję utoźsamienie tablica-wskaźnik)
Drugi sposłb powtłrzony: r-mi 13-01-2007 00:49
Wtedy przekazujesz wskaźnik do pojedynczego elementu i sam wyliczasz przesunięcie. To trochę bardziej elastyczne, ale i odpowiadasz za dobre indeksowanie sam. I inne typy w deklaracji.


No i??
Nic, źle uźyłeś pojęcia rekurencja. Ta sprawa zamknięta.

macol
31-01-07, 13:58
Nic, źle uźyłeś pojęcia rekurencja. Ta sprawa zamknięta.
Moźe i jestem mocno początkujący w c++, ale nie wciskaj mi źe nie wiem o czym młwię. Funkcja ktłrą potrzebowałem wywołać rekurencyjnie zawierała w deklaracji tablice wielowymiarową, dlatego o tym wspomniałem. Dobrze uźyłem pojęcia rekurencja.

macol
31-01-07, 20:37
moźe ktoś zdąźy jeszcze dzisiaj pomłc...

mam ułamek double, ktłry ma wartość mniej więcej taką : 0,1250000, albo 0,500000.
Jak spowodować źeby na wyjściu(najlepiej cout) w kaźdym systemie(zapewne jakiś unix/linux, kompilator g++ 4.0.0 -8 ) ułamek pojawił się w najmniejszej moźliwej postaci, czyli 0,125 i 0,5?

W win on mi się zawsze taki pokazuje, ale na maszynie testowej pojawia się chyba coś innego.

roosterek
31-01-07, 21:17
mam ułamek double, ktłry ma wartość mniej więcej taką : 0,1250000, albo 0,500000.
Jak spowodować źeby na wyjściu(najlepiej cout) w kaźdym systemie(zapewne jakiś unix/linux, kompilator g++ 4.0.0 -8 ) ułamek pojawił się w najmniejszej moźliwej postaci, czyli 0,125 i 0,5?

W win on mi się zawsze taki pokazuje, ale na maszynie testowej pojawia się chyba coś innego.

Myślałem, źe kaźdy system obcina niepotrzebne zera, bo imho 0,125=0,1250000.
Tak przynajmniej jest w matematyce, no chyba, źe za tymi zerami coś istotnego jeszcze stoi, to wtedy oczywiście zostają.

macol
31-01-07, 22:27
0,125=0,1250000
no tak, ale zapis inny... a w tym wypadku zapis ma być bez zer... coś zawalczyłem, i niby mam, ale dalej gdzieś jest błąd... i 30 minut na jego znalezienie... chyba idę idę spać :D

r-mi
01-02-07, 09:25
printf("%.2d", zmienna) albo printf("%2d", zmienna)

Poza tym (zalenie od implementacji) 0,5 w systemie zmiennoprzecinkowym moe wynie np. 0,496666666 - dlatego np. do preprezentacji danych finansowych zawsze uywa si integer. Float ma jeszcze jedn ciekaw wasno, e im liczba bardziej oddalona od przyjtego rodka osi liczbowej - tym dokadno maleje. Dlatego np. za pomoc 32 bit mona zapisa int ktry wymaga 64 bit, ale potem si okazuje np. e 102938888,23 = 102939552,5531

W odrnieniu od int - implementacja double / float nie jest staa pomidzy systemami (w sumie implementacja int te nie jest zawsze LE/BE, ale przynajmniej dokadno ju sta maj)

Jeli chcesz mie pewn dokadno czyli zapisa liczb zmiennoprzecinkow tak jak "wyglda w wiecie rzeczywistym" uywasz staoprzecinkowej zmiennej (integer) i odpowiednio wywietlasz wynik, np w tym wypadku.

int zmienna = 1021; // 10,21
count << zmienna/100 << ',' << zmienna % 100;


Mylaem, e kady system obcina niepotrzebne zera
le podszede do problemu. Double, float i oglnie dziaania matematyczne na komputerze nie maj nic wsplnego z matematyk ze szkoy. Jeli liczysz co w jzyku niskopoziomowym (np. C) to nie obowizuj adne prawa klasycznej matematyki nawet tak banalne i oczywiste jak prawo przemiennoci dodawania (a+b nie koniecznie = b+a nawet dla int a dla float to dopiero). Wic wszystko czego ucz od IV podstawwki i jest np. na tej stronie mona sobie wsadzi http://www.ipe.pl/archiwum/+/html/prace/swoboda/regulki.htm


bo imho 0,125=0,1250000
Wanie w tym jest problem, e "dla komputera" nie koniecznie. W implementacji C double 0,125 wynosi pewnie co w stylu 0,12500000000012 teraz pewnie funkcja wywietlania na ekran w jednym wypadku wemnie pod uwag defaultow ilo miejsc po przecinku i obetnie zera dla przycitej wartoci, druga obetnie zera tylko dla bazowej wartoci, np.

1. 0,125 -> (pami) -> 0,12500000000120000 -> (obcinamy zera) -> 0,1250000000012 (dokadno domylna) -> 0,12500000000 -> (wywietlamy)

2. 0,125 -> (pami) -> 0,12500000000120000 -> (dokadno domylna) -> 0,12500000 (obcinamy zera) -> 0,125 -> (wywietlamy)

Najlepiej bdzie jak zapomnisz to czego nauczye si w szkole na matematyce dla potrzeb programowania w C, bo bdziesz si tylko niepotrzebnie gowi "czemu to dziaa nie tak jak >musi<" podczas, gdy "dziaa jak musi". W sumie te prawa nie s bardziej skomplikowane ni to czego uczy si w podstawwce na matematyce, jednak to e zamiast rzeczy przydatnych w szkoach uczy si rzeczy skomplikowanych to inna kwestia ;)


niby mam, ale dalej gdzie jest bd...
Wanie nie ma adnego bdu... no chyba, e potrzebujesz wasnoci staoprzecinkowego systemu liczbowego a wykorzystae system zmiennoprzecinkowy.

macol
01-02-07, 13:20
Właśnie nie ma źadnego błędu... no chyba, źe potrzebujesz własności stałoprzecinkowego systemu liczbowego a wykorzystałeś system zmiennoprzecinkowy.Jest, bo system wyniki odrzucał, moźe jakiś inny błąd w algorytmie...
Ale teraz to mnie juź bokiem obchodzi... jedyne co, to to, źe będę klął ok 15 lutego, a ok 20 leczył kaca... albo będę happy, a kaca zacznę leczyć tydzień płźniej...
Z mojej strony temat chyba zamknięty.

bombellb
09-02-07, 01:53
myślenie że 0.25=0.250000000000000 jest conajmniej nieporozumieniem. Każda liczba jest zapisywana z pewną dokładnością. Dla typu double jest to ok. 17 liczb po przecinku. tak więc 0.25=0.250000000000001 niby niewiele ale w większych programach numerycznych robi różnicę. Tak na marginesi to uruchom deburgera i sprawdź sobię czy rzeczywiście 0.25=0.25

bombellb
09-02-07, 01:59
dodam że jeżeli chcesz aby wyświetlało ci np. z zaokrągleniem do drugiego miejsca po przecinku to napisz:
cout.preciosion(2). Można używać funkcji floor i ceil ale trzeba napisać do nich funkcję aby wiedzieć czy zaokrąglać w górę czy w dół