Avatar
Peta
Člen
Avatar
Peta:

Ahoj, nevíte někdo prosím, jak mám udělat tento úkol?
Vytvořte program, který po načtení desetinného čísla a přesnosti vypíše zadané
číslo po zaokrouhlení na zadanou přesnost.
Př:
Číslo: 8.2483
Přesnost: 0.01
Zaokrouhleno: 8.25

 
Odpovědět 6.10.2015 21:38
Avatar
Pjanus
Člen
Avatar
Odpovídá na Peta
Pjanus:

No mohl by si to třeba udělat tak že bys vydělil zadané číslo přesností 8.2483 / 0.01 = 824.83 poté bych si tu hodnotu uložil a převedl to číslo z desetinného na celé. Takže v paměti jsou dvě čísla, ty bych od sebe odečetl (float)824.83 - (int)824 z čehož by vznikl výsledek 0.83 který se dá jednoduše porovnat jestli je větší nebo roven 0.5. Podle toho by se rozhodlo jestli se číslo (int) zvýší o jedna. Na konci procesu stačí vynásobiz výsledek v tomto případě 825 původní přesností 0.01 což nám 825 * 0.01 = 8.25. Ale taky je možný že to dělám příšerně složitě ale mohlo by ti to alespoň dát nápad ;)

 
Nahoru Odpovědět 6.10.2015 21:51
Avatar
Sony Nguyen
Redaktor
Avatar
Sony Nguyen:

Přikládám také moje řešení :).
číslo = 8.2483
přesnost = 0.01
toCoSmažeme = číslo % přesnost

pokud je toCoSmažeme / přestnost větší nebo rovno 0.5, tak číslo += přesnost
jinak nic nedělej

číslo = číslo - číslo % přesnost

implementace v Pythonu 2.7

def zaokrouhli(cislo, presnost):
        zbytek = cislo % presnost

        if zbytek / presnost >= 0.5:
                cislo += presnost
        return cislo - zbytek

Přesnost by měla být vždy typu float/double
ale není to ošetřeno proti nevalidním vstupům
PS. Snad pomohlo :), uznávám, že je to trochu magické :D

Editováno 6.10.2015 22:24
 
Nahoru Odpovědět  +2 6.10.2015 22:23
Avatar
coells
Redaktor
Avatar
Odpovídá na Sony Nguyen
coells:

Sony, jsi blízko, ale modulo se považuje za pomalou operaci.
Kód se dá zjednodušit, v případě pythonu 3 by to bylo:

def zaokrouhli(cislo, presnost):
    return int(cislo / presnost + .5) * presnost

Plus je ještě nutné vzít v úvahu záporná čísla.

 
Nahoru Odpovědět 7.10.2015 0:05
Avatar
David Novák
Tým ITnetwork
Avatar
Odpovídá na coells
David Novák:

Jen bych podotkl, že dělení je naprosto stejně pomalé jako modulo (obě se provádí zároveň při každé instrukci DIV) :)

Nahoru Odpovědět  +1 7.10.2015 8:36
Chyba je mezi klávesnicí a židlí.
Avatar
Odpovídá na Peta
Libor Šimo (libcosenior):

Úloha je veľmi jednoduchá:

#include <stdio.h>

int main(void)
{
    float f = 8.2483;
    printf("%.2f\n", f);
    return 0;
}
;-)
Nahoru Odpovědět  +1 7.10.2015 8:55
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
Libor Šimo (libcosenior):

Poprípade trošku rozšírené:

#include <stdio.h>

int main(void)
{
    float f;

    printf("Zadajte desatinne cislo: ");
    scanf("%f", &f);
    printf("%.2f\n", f);

    return 0;
}
Nahoru Odpovědět 7.10.2015 8:58
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
coells
Redaktor
Avatar
Odpovídá na David Novák
coells:

Překvapivě to není pravda pokud budeme mluvit o celočíselném dělení.
Modulo je opravdu pomalejší - a ano, vím, jak fungují instrukce div a idiv.
U posuvné řádové čárky je na to speciální instrukce, takže by to snad mělo být stejně rychlé, ale to jsem nikdy nezkoušel.

 
Nahoru Odpovědět 7.10.2015 19:21
Avatar
David Novák
Tým ITnetwork
Avatar
Odpovídá na coells
David Novák:

Vidíš to - FPU dělení / modulo jsem nebral v potaz...

Zajímalo by mě ale, jak může být při použití DIV modulo pomalejší, když jedna operace vrací oba výsledky.. Vysvětlíš?

Nahoru Odpovědět 7.10.2015 19:45
Chyba je mezi klávesnicí a židlí.
Avatar
coells
Redaktor
Avatar
Odpovídá na David Novák
coells:

Nevysvětlím, bohužel.
Dokonce jsem to zkoušel a na mém CPU jsou opravdu stejně rychlé.
Ale mám opačnou zkušenost z minula ze soutěží, kdy odstranění modula výrazně pomohlo.

 
Nahoru Odpovědět 7.10.2015 20:11
Avatar
Petr Valigura
Redaktor
Avatar
Petr Valigura:

Hádám kolega z UPOL? :D (já jenom, že my jsme dostali úplně stejný úkol) Moje řešení

int main() {
        double cislo, zaokrouhleneCislo, presnost;
        printf("Zadej cislo: ");
        scanf("%lf", &cislo);
        printf("Zadejte presnost: ");
        scanf("%lf", &presnost);
        zaokrouhleneCislo = ((long int)(cislo / presnost + 0.5)) * presnost;
        printf("%f \n", zaokrouhleneCislo);
        system("pause");
        return 0;
}

Funguje jen u kladných, kdyby jsi chtěl i u záporných, tak to číslo prvně převeď na kladné (...*(-1)) a pak zase zpátky na záporné :)

Nahoru Odpovědět 7.10.2015 20:28
Občas je to tady dobrá klauniáda...
Avatar
David Novák
Tým ITnetwork
Avatar
Odpovídá na coells
David Novák:

Ono asi hodně záleží na použitém jazyku a kvalitě překladače..

Pokud bychom například v C napsali:

int a,b;
int deleni = a / b;
int modulo = a % b;

Měl by z toho překladač se zapnutou optimalizací udělat něco takového:

mov eax, [a]
cdq
mov ebx, [b]
div ebx
mov [deleni], eax
mov [modulo], edx

Takže použití těchto dvou operací nad stejnými operandy by vůbec nemělo být zpomalující. Jak se k tomu staví jiné překladače a vyšší jazyky ale nevím, takže těžko říct no.. Možná se jednalo o nějakou chybu, která byla vyřešena. :)

Nahoru Odpovědět 7.10.2015 20:54
Chyba je mezi klávesnicí a židlí.
Avatar
coells
Redaktor
Avatar
Odpovídá na David Novák
coells:

Spíš je to ještě složitější. Pokud totiž počítáš modulo přes konstantu, která je známá během kompilace, kompilátor se za každou cenu vyhne dělení, viz příloha. To by vysvětlovalo, proč je modulo pomalé v komplikovaném kódu, kde může blokovat další optimalizace.

 
Nahoru Odpovědět 7.10.2015 21:33
Avatar
David Novák
Tým ITnetwork
Avatar
Odpovídá na coells
David Novák:

Aha.. Zajímavé..

Tak ono je fakt, že dělení je jedna z nejnáročnějších operací a proto je snaha se tomu vyhýbat..

Co se týče příkladu, mohl bys mi prosím vytáhnout část, která realizuje to modulo? Je to to, jak jsou tam posuny vpravo? A 'q' za instrukcí znamená přesně co..? 4 bajty? přiznávám, že jsem prakticky vždy pracoval s NASM syntaxí, takže v této se moc nevyznám.. :D

Nahoru Odpovědět 7.10.2015 21:47
Chyba je mezi klávesnicí a židlí.
Avatar
coells
Redaktor
Avatar
Odpovídá na David Novák
coells:

Je to obyčejný while cyklus pro převod do K-ární soustavy, tedy mod-div-print.
0f14 začíná mod/div
0f33 plní argumenty pro printf

q znamená quad prefix instrukce.
NASM je o dost jednodušší, ale tu jsem na linuxu nikdy neviděl :-)

 
Nahoru Odpovědět 7.10.2015 22:15
Avatar
David Novák
Tým ITnetwork
Avatar
Odpovídá na coells
David Novák:

No jednak tam existuje přímo nasm.. Ale i v gas se to dá snadno nastavit :)

.intel_syntax noprefix
Nahoru Odpovědět  +1 7.10.2015 22:20
Chyba je mezi klávesnicí a židlí.
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 16 zpráv z 16.