• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

liczenie int signed i unsigned

VPS Starter Arubacloud
0 głosów
292 wizyt
pytanie zadane 27 września 2022 w C i C++ przez Nahlfar Nowicjusz (220 p.)

Znalazłem taki kod jako rozwiązanie zadania MWPZ06A Ciążowy Specjalista:

unsigned N, X, Y, Z;
    for (cin >> N; N--; cout << (unsigned)(12 * (Y - X / (Z - 1.)) + 0.5) << endl) cin >> X >> Y >> Z;

Nie rozumiem tego kodu, bo gdziekolwiek czytam opis pętli for, to mam taki:

for (initialization; condition; increase) statement;

czyli intialization to wczytanie N. I to jest jedyny element który rozumiem smiley

Pytanie 1. Condition to N--. Tego nie rozumiem. Jak warunkiem może być zmniejszenie N? Przede wszystkim warunek to tylko porównanie i nie powinien być wykonywany..? A tutaj jest wykonywany? Dlaczego? frown 
Pomijając fakt wykonania, to rozumiem, że pętla będzie wykonywana do momentu uzyskania FALSE, tj. N stanie się zero.

Pytanie 2. increase to cout. To już najbardziej mnie rozwala... przecież tutaj nie ma żadnego increase i ten kod nie jest zgodny z definicją... :( chcę płakać, bo ktoś mnie tu oszukuje...

Jeszcze na koniec same wyliczenia to kolejny koszmar, którego nie rozumiem crying

Pytanie 3. Dlaczego we wzorze mamy jeden z kropką? Mam na myśli (Z-1.). Co to ma za znaczenie, czy 1 jest z kropką czy bez?

Pytanie 4. Dlaczego w tym wzorze dodaje 0.5? Gdy liczę tym wzorem na signed int, to daje mi złe rezultatu. Czyli dla przykładowych wejść wychodzi 9.5, 1.5, etc. Z kolei ten wzór działa gdy wszystkie zmienne są zdefiniowane jako unsigned, a wynik ze wzoru jest rzutowany na unsigned.

Samemu napisałem taki wzór: cin >> X >> Y >> Z; cout <<  (-12 * ((X + Y) - Y * Z) / (Z - 1)) << endl;

W tej sytuacji oba wzory dają te same, prawidłowe rezultaty:

unsigned int X, Y, Z;
        cin >> X >> Y >> Z;
        cout <<  (-12 * ((X + Y) - Y * Z) / (Z - 1)) << endl;
        cout << (unsigned)(0.5+ 12 * (Y - X / (Z - 1.)) ) << endl;

Natomiast w poniżeszej sytuacji pierwszy wzór daje dziwne, bardzo wysokie wartości (rozumiem, że to z powodu usunięcia ujemnych i przesunięcia wartości), ale drugi wzór nadal daje prawie dobry wynik tylko, że za duży o te dziwne 0.5. Pytanie 5. Dlaczego drugi wzór nie został przesunięty po usunięciu ujemnych?

unsigned int X, Y, Z;
        cin >> X >> Y >> Z;
        cout <<  (unsigned)(-12 * ((X + Y) - Y * Z) / (Z - 1)) << endl;
        cout << (0.5+ 12 * (Y - X / (Z - 1.)) ) << endl;

 

komentarz 27 września 2022 przez Whistleroosh Maniak (56,900 p.)

W razie wątpliwości zawsze najlepiej przeczytać dokumentacje :)

en.cppreference.com/w/cpp/language/for

komentarz 27 września 2022 przez Nahlfar Nowicjusz (220 p.)
Pominąłeś pytania 3, 4 i 5. Podpowiesz coś w ich zakresie?

Odnosząc się do linku:

Patrząc na definicję formalną z Twojego linku, to mamy tylko jeden średnik i dwa argumenty. W pierszym argumencie init-statement condition oddzielone tylko spacją. Nigdy nie widziałem takiego kodu. Nawet ten, o który pytam, używa dwóch średników, a init jest oddzielony od condition poprzez średnik, a nie spację.
Patrząc na definicję informal, to tam nie ma żadnego condition. Czyli znowu zamieszanie i brak spójności.

To wymaga wytłumaczenia i dlatego proszę o pomoc.
1
komentarz 27 września 2022 przez Oscar Nałogowiec (29,290 p.)
edycja 27 września 2022 przez Oscar

@Nahlfar, 

pętla

for (A;B;C)
     D;

to po prostu jest to samo co:

A;
while (B)
{
    D;
    C;
}

Cała reszta z tego wynika.

Ad 1 - w C prawie każda instrukcja to wyrażenie dające jakiś wynik. Wynikien N-- jest wejściowa wartość N. A jako warunek sprawdzane jest czy ta wartość jest różna od zera.

Ad 3.  1. to float, 1 bez kropki to int. Dzielenie dwóch intów to inna operacja niż dzielenie z udziałem float. Zwykle jeden z argumentów w type float "promuje" całe wyrażenie do operacji zmiennoprzecinkowych. Przypomnij sobie początkowe zajęcia z matematyki z podstawówki (mało kto to pamięta) - zajęcia o zbiorach, dzieleniu z resztą itp.

Ad 4. Dodanie 0.5 pewnie służy do uzyskania zakrąglenia matematycznego zamiast obcięcia części ułamkowej (a tak działa rzutowanie).

 

PS. nie podałeś jakiegoś konkretnego linku do treści zadania, więc go nie znam i nie mam jak odnieść się do pytania 2.

 

komentarz 27 września 2022 przez Nahlfar Nowicjusz (220 p.)

@Oscar

Tutaj link do zadania: zadanie ale pytanie 2 możesz uznać za zamknięte, bo pytania 1 i 2 dotyczyły tego samego, czyli pętli for. For wytłumaczyłeś mi dosyć dobrze i rozumiem jego zastosowanie w tej kluczowej linijce kodu. Natomiast nadal nie rozumiem tych definicji z oficjalnej dokumentacji, lub typowego dla nauki C wytłumaczenia: for (initialization; condition; increase) statement;
Dlaczego nikt tego normalnie nie uczy zamiast podawać sekwencje init, condition, increase, statement...?

Ad 3. W jaki sposób dzielenie dwóch intów jest inną operacją niż dzielenie dwóch floatów?
Na pewno na początkowych zajęciach z matematyki nie tłumaczą wykonywania operacji zmiennoprzecinkowych...

Ad 4. W jaki sposób dodanie 0.5 może powodować zaokrąglenie?

No i jeszcze pytanie 5. Chciałbym to móc jakoś przeanalizować i dlatego proszę o pomoc.

 

komentarz 27 września 2022 przez Whistleroosh Maniak (56,900 p.)

(-12 * ((X + Y) - Y * Z) / (Z - 1))

Testowałeś ten wzór na SPOJu? Bo u mnie nie przechodzi i w sumie nie powinno przejść

komentarz 27 września 2022 przez Whistleroosh Maniak (56,900 p.)
cout << 5/2;
cout << 5./2.;

Prosty przykład dlaczego dzielenie intów to nie to samo co dzielenie floatów

cout << int(5./2.);
cout << int(5./2.+0.5);

I kolejny przykład dlaczego 0.5 zaokgrągla w góre. Ogólnie int(x), gdzie x to float powoduje usunięcie części ułamkowej

komentarz 28 września 2022 przez mokrowski Mędrzec (155,460 p.)

@Whistleroosh @Oscar To są typy double a nie float'y.

komentarz 28 września 2022 przez Nahlfar Nowicjusz (220 p.)

@Whistleroosh, 

Tak testowałem. Jeżeli wejściem są signed int, to jak najbardziej liczył. Nie wiem dlaczego, ale ten wzór pada, gdy używam unsigned int.

Natomiast wzór, który znalazłem działa zarówno na signed i unsigned. Dlaczego?

Matematycznie patrząc to: (Y - X / (Z - 1.)) jest tylko skótem od -(X + Y - Y * Z) / (Z - 1.), bo wyciągam Z-1 w nawias i wtedy -(X -Y*(Z-1))/(Z-1)= Y-X/(Z-1).

Jeżeli matematycznie oba wzory są takie same, to dlaczego z unsgined int i signed int dają inne rezultaty?

komentarz 28 września 2022 przez Whistleroosh Maniak (56,900 p.)

Już zaczyna mi się mieszać, który wzór nie działa dla których typów zmiennych?

int(0.5 + -12 * ((X + Y) - Y * Z) / (Z - 1.))
unsigned(0.5 + -12 * ((X + Y) - Y * Z) / (Z - 1.))
int(0.5 + 12 * (Y - X / (Z - 1.)))
unsigned(0.5 + 12 * (Y - X / (Z - 1.)))

Te wzory powinny przejść testy SPOJa niezależnie od tego czy typ zmiennych to int czy unsigned. Tylko trzeba uważać bo w niektórych zachodzi integer overflow, więc jak wstawisz gdzieś dodatkowe nawiasy to mogą wyjść zupełnie inne wyniki.

Zaloguj lub zarejestruj się, aby odpowiedzieć na to pytanie.

Podobne pytania

0 głosów
1 odpowiedź 245 wizyt
pytanie zadane 16 lutego 2018 w C i C++ przez Shiro Stary wyjadacz (10,300 p.)
0 głosów
2 odpowiedzi 788 wizyt
pytanie zadane 11 września 2016 w C i C++ przez rubiikk Obywatel (1,900 p.)

92,453 zapytań

141,262 odpowiedzi

319,088 komentarzy

61,854 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Akademia Sekuraka 2024 zapewnia dostęp do minimum 15 szkoleń online z bezpieczeństwa IT oraz dostęp także do materiałów z edycji Sekurak Academy z roku 2023!

Przy zakupie możecie skorzystać z kodu: pasja-akademia - użyjcie go w koszyku, a uzyskacie rabat -30% na bilety w wersji "Standard"! Więcej informacji na temat akademii 2024 znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...