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

[c++] Niezrozumiałe zachowanie programu / zmiana typu zmiennej

VPS Starter Arubacloud
+1 głos
508 wizyt
pytanie zadane 3 listopada 2017 w C i C++ przez PanJaqb Początkujący (360 p.)

Witam,

Rozwiązuje zadanie domowe ze SPOJa 626 "obzartuchy". I w moim algorytmie dzieje się coś czego nie umiem wytłumaczyć, a mianowicie:

dlaczego zmiana typu zmiennej między z float i int zmienia wynik na wyjściu jeśli w jednym i drugim wypadku podaję tę samą liczbę czyli 10

Wejście

2
2 10
3600
1800
3 356
123
32999
10101

Wyjście

8
2

Jeśli zmienna cakes_in_box jest intem na wyjściu otrzymuję 7 jeśli floatem to 8. O co chodzi? przecież za każdym razem wprowadzam w 1 iteracji pętli for cakes_in_box = 10

kod:

#include <iostream>
#include <math.h>

int main()
{
    int test;
    std::cin >> test;

    for (int i=1; i<=test; i++)
    {
        int gruzzlers;
        std::cin >> gruzzlers;

        int cakes_in_box;
        std::cin >> cakes_in_box;
        //std::cout << "pokaz: " << cakes_in_box;

        int g1eat_time;
        std::cin >> g1eat_time;

        int g2eat_time;
        std::cin >> g2eat_time;

        int t24h = 24*60*60;
        int g1cakes_eat_in24h= t24h / g1eat_time;
        int g2cakes_eat_in24h= t24h / g2eat_time;

        if (gruzzlers==3)
        {
            int g3eat_time;
            std::cin >> g3eat_time;

            int g3cakes_eat_in24h= t24h / g3eat_time;

            float x =((g1cakes_eat_in24h+g2cakes_eat_in24h+g3cakes_eat_in24h)/cakes_in_box);
            //std::cout << x;

            int y = ceil(x);
            std::cout << y << std::endl;
        }
        else
        {
            float x = ((g1cakes_eat_in24h+g2cakes_eat_in24h)/cakes_in_box);
            //std::cout << x;

            int y = ceil(x);
            std::cout << y << std::endl;
        }
    }

 return 0;
}

 

2 odpowiedzi

+1 głos
odpowiedź 4 listopada 2017 przez draghan VIP (106,230 p.)
wybrane 4 listopada 2017 przez PanJaqb
 
Najlepsza

Jeśli zmienna cakes_in_box jest intem na wyjściu otrzymuję 7 jeśli floatem to 8

W C oraz C++ rozróżniamy operator dzielenia całkowitoliczbowego oraz zmiennoprzecinkowego. Mimo że jego identyfikatorem jest ten sam znak "/", działanie jest nieco inne: operator dzielenia zmiennoprzecinkowego zwróci spodziewany wynik z częścią ułamkową ("po przecinku"), zaś operator dzielenia całkowitoliczbowego zwróci wynik z dzielenia pozbawiony części ułamkowej.

Kiedy jaki operator jest wywoływany, jeśli oba mają ten sam identyfikator? Decydują tutaj typy, z jakimi jest wywoływany. Zasada jest prosta: jeśli choć jeden argument jest typu zmiennoprzecinkowego, wybierany jest operator dzielenia zmiennoprzecinkowego; jeśli nie - całkowitoliczbowego.

Przykład:

float result;

int i = 10;
float f = 3.0f;

// wydrukuj sobie wyniki każdej z operacji :)
result = 10 / 3; // oba argumenty są całkowite - wywołany operator dzielenia całkowitoliczbowego
result = i / 3; // dokładnie jak wyżej

result = 10 / 3.0; // jeden argument jest zmiennoprzecinkowy = operator dzielenia zmiennoprzecinkowego
result = i / f; // jak wyżej
result = f / 2; // jak wyżej
result = f / 2.0; // dwa argumenty są zmiennoprzecinkowe = operator dzielenia zmiennoprzecinkowego
result = f / f; // jak wyżej

 

komentarz 4 listopada 2017 przez PanJaqb Początkujący (360 p.)
dziękuje teraz wszystko rozumiem, mam jeszcze jedno pytanie, otóż:
czy pomimo tego, że działanie złożone jest z intów, mogę w jakiś sposób wymusić wynik działania na zmiennoprzecinkowy?
próbowałem:
x = float ( działanie) niestety nie działa :P
1
komentarz 4 listopada 2017 przez draghan VIP (106,230 p.)

czy pomimo tego, że działanie złożone jest z intów, mogę w jakiś sposób wymusić wynik działania na zmiennoprzecinkowy?

Jasne, można użyć rzutowania. W C++ powinno się to robić w ten sposób:

float result;

int a = 10;
int b = 3;

result = a / b; // oba operandy są całkowitoliczbowe
result = a / static_cast<float>(b); // pierwszy operand jest całkowitoliczbowy, drugi rzutujesz (konwertujesz) na typ float

EDIT:

x = float ( działanie) niestety nie działa :P

Prawie dobrze kombinujesz. ;) Tylko obejmując rzutowaniem całe działanie, i tak pozwalasz na wywołanie operatora dzielenia całkowitoliczbowego. Musisz rzutować składniki dzielenia (lub chociaż jeden składnik, jak w przykładzie).

komentarz 4 listopada 2017 przez PanJaqb Początkujący (360 p.)

dzięki! 
Jeszcze jedno pytanie czy użycie komendy static_cast jest niezbędne czy można pominąć i napisać (na Twoim przykładzie) 

resault = a / float(b);

 

1
komentarz 5 listopada 2017 przez draghan VIP (106,230 p.)

Móc - można. Ten rodzaj rzutowania jest w C++ odziedziczony po C i jest niezalecany. Problemem rzutowania w stylu C jest to, że dla każdej, nawet potencjalnie niebezpiecznej konwersji, wygląda on tak samo niewinnie. W C++ do rzutowania stworzono zestaw operatorów, które jasno wyrażają intencję programisty.

  • const_cast - do rzutowań zmiennych, modyfikując kwalifikatory const i volatile,
  • static_cast - do naturalnych rzutowań, które są dość oczywiste, jak właśnie np. z int na float,
  • dynamic_cast - do rzutowań na typy w łańcuchu dziedziczenia,
  • reinterpret_cast - do rzutowań potencjalnie niebezpiecznych, zatracających informacje o pierwotnym typie, jak np. rzutowanie typu wskaźnikowego na typ liczbowy lub rzutowania zmieniające typ wskaźnikowy na inny.
komentarz 5 listopada 2017 przez PanJaqb Początkujący (360 p.)
Dzięki, zatem będę używał operatora. Jeśli chodzi o const, dynamic, reinterpret nie jest to dla mnie na tą chwilę w ogóle zrozumiałe, ale to już poczytam sobie w zakresie własnym i miejmy nadzieję będzie mi dane wykorzystać w praktyce.

Jeszcze raz dzięki!
0 głosów
odpowiedź 3 listopada 2017 przez Undisputed Gaduła (3,040 p.)
Jak masz int i masz liczbę 7,334 to wypisze 7
Jeśli masz float i masz liczbę 7,334 i dasz ceil() to zaokrągli w górę i da 8
komentarz 3 listopada 2017 przez PanJaqb Początkujący (360 p.)
no tak, ale ja nie zaokrąglam zmiennej cakes_in_box która zawsze w 1 iteracji wynosi 10, tylko zmienną x która zawsze jest floatem
komentarz 3 listopada 2017 przez PanJaqb Początkujący (360 p.)

uproszczony kod:

#include <iostream>
#include <math.h>

int main()
{
    int test;
    std::cin >> test;

    int gruzzlers;
    int cakes_in_box;
    int g1eat_time;
    int g2eat_time;
    int g3eat_time;
    int t24h = 24*60*60;
    int g1cakes_eat_in24h;
    int g2cakes_eat_in24h;
    int g3cakes_eat_in24h;
    float x;
    int y;

    for (int i=1; i<=test; i++)
    {

        std::cin >> gruzzlers;
        std::cin >> cakes_in_box;
        std::cin >> g1eat_time;
        std::cin >> g2eat_time;
        g1cakes_eat_in24h= t24h / g1eat_time;
        g2cakes_eat_in24h= t24h / g2eat_time;

        if (gruzzlers==3)
        {
            std::cin >> g3eat_time;
            g3cakes_eat_in24h= t24h / g3eat_time;
            x = ((g1cakes_eat_in24h+g2cakes_eat_in24h+g3cakes_eat_in24h)/cakes_in_box);
            y = ceil(x);
            std::cout << y << std::endl;
        }
        else
        {
            x = ((g1cakes_eat_in24h+g2cakes_eat_in24h)/cakes_in_box);
            y = ceil(x);
            std::cout << y << std::endl;
        }
    }

 return 0;
}

 

komentarz 3 listopada 2017 przez PanJaqb Początkujący (360 p.)
spostrzeżenia:

x - jest floatem, ale wartość jego określona równaniem złożonym z intów daje inny wynik niż w sytuacji gdzie chociaż jedna ze zmiennych jest floatem.

To dla mnie dziwne

Podobne pytania

+1 głos
3 odpowiedzi 1,208 wizyt
pytanie zadane 9 lutego 2021 w C i C++ przez melman666 Nowicjusz (210 p.)
0 głosów
2 odpowiedzi 199 wizyt
pytanie zadane 22 października 2016 w C i C++ przez MsMaciek123 Pasjonat (24,760 p.)
+2 głosów
3 odpowiedzi 238 wizyt
pytanie zadane 13 grudnia 2021 w PHP przez Bakkit Dyskutant (7,600 p.)

92,452 zapytań

141,262 odpowiedzi

319,085 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!

...