• 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

Aruba Cloud PRO i VPS, Openstack, VMWare, MS Hyper-V
+1 głos
376 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,020 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,020 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,020 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 519 wizyt
pytanie zadane 9 lutego 2021 w C i C++ przez melman666 Nowicjusz (210 p.)
0 głosów
2 odpowiedzi 122 wizyt
pytanie zadane 22 października 2016 w C i C++ przez MsMaciek123 Pasjonat (24,780 p.)
+2 głosów
3 odpowiedzi 95 wizyt
pytanie zadane 13 grudnia 2021 w PHP przez Bakkit Dyskutant (7,610 p.)

89,768 zapytań

138,375 odpowiedzi

309,458 komentarzy

59,679 pasjonatów

Advent of Code 2022

Top 15 użytkowników

  1. 1074p. - Argeento
  2. 1010p. - rucin93
  3. 1006p. - Michal Drewniak
  4. 1000p. - Łukasz Eckert
  5. 974p. - TheLukaszNs
  6. 949p. - JMazurkiewicz
  7. 946p. - adrian17
  8. 933p. - Jarosław Roszyk
  9. 889p. - nidomika
  10. 860p. - Mikbac
  11. 847p. - ssynowiec
  12. 799p. - Hubert Chęciński
  13. 772p. - Mawrok
  14. 768p. - overcq
  15. 764p. - Vinox
Szczegóły i pełne wyniki

Motyw:

Akcja Pajacyk

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

Sklep oferujący ćwiczenia JavaScript, PHP, rozmowy rekrutacyjne dla programistów i inne materiały

Oto dwie polecane książki warte uwagi. Pełną listę znajdziesz tutaj.

...