« 1 2
Autor Zpráva
Jan Tvrdík
Profil
Chamurappi:
Mimochodem, pro jaké n neplatí (...)?
Pro libovolná lichá n. Příklad v C a v PHP.
Joker
Profil
Chamurappi:
Pravda, ta původní úvaha asi nedostatečně zohlednila, že jednak ta přesnost je od první platné číslice a jednak těch řádů tam je poměrně hodně.

Ale jistá varianta toho problému může být třeba tohle:
var lower = 9876543210000000;
var upper = 9876543210000099;
for (var i = lower; i < upper; i++) {
…
}
versus
var lower = 9876543210000000;
var upper = 9876543210000099;
for (var i = 0; i < (upper - lower); i++) {
…
}

Dodatek:
Taková docela zajímavá perlička je, že výsledkem konstrukce: for (var i = (limit - 100); i < limit; i++) může v závislosti na hodnotě limit být 100 cyklů, nekonečný cyklus nebo žádný cyklus.
Chamurappi
Profil
Reaguji na Jana Tvrdíka:
Příklad v C a v PHP.
Céčkový příklad používá int. Péhápéčkový vrací v obou případech hodnotu 3.
V JavaScriptu je všechno double.


Reaguji na Jokera:
jistá varianta toho problému může být třeba tohle
Ano, ale vyhnat mantinely cyklu do takových výšin obvykle postrádá smysl. Není to realistická situace, kdy by si nic netušící člověk řekl „sakra, co se to děje, JS neumí počítat?“ … do tohohle stavu se dá dostat skoro jen záměrně, když si chce programátor na nepřesnost čísel úmyslně posvítit. Narazit omylem na výraznou nepřesnost způsobenou drobnou odchylkou v mezivýpočtu asi jen tak nepůjde.

versus
Ve druhém kódu vyjde upper - lower rovná stovka, protože upper se ve skutečnosti uloží jako 9876543210000100. Sice je to lepší než nekonečná smyčka, ale k na první pohled očekávatelným 99 průchodům to nevede.

může v závislosti na hodnotě limit být 100 cyklů, nekonečný cyklus nebo žádný cyklus
Nebo také 101 cyklů, třeba pokud je limit rovný Number.MIN_VALUE.
_es
Profil
Jan Tvrdík:
Chamurappi:
„Mimochodem, pro jaké n neplatí (...)?“
Pro libovolná lichá n. Příklad v C a v PHP.
Ale tu išlo o typ double v C. Tam to je jedno, lebo pri delení dvomi sa len zmenší exponent čísla o 1.
SeparateSK
Profil
Jan Tvrdík:
Příklad v C
#include <cstdio>
 
int main()
{
    int n = 3; // libolné liché
    printf("n * (n - 1) / 2 = %d\n", n * (n - 1) / 2);
    printf("n / 2 * (n - 1) = %d\n", n / 2 * (n - 1));
    return 0;
}
int nemá desatinné miesta, teda výsledok 1.5 akoby prejde cez floor(...) => 1
Teda to je to isté ako: floor(3/2)*(n-1);


http://ideone.com/UHg7oJ - s double
Jan Tvrdík
Profil
_es, SeparateSK:
Tak nějak nechápu, proč mi to vysvětlujete. Já chápu velmi dobře, proč se to tak chová. Ta myšlenka byla, že tam, kde v matematice na pořadí operací nezáleží, v programování může.
SeparateSK
Profil
Ale ani v matimatike to nie je jedno, keď počítame s celými číslami a nie desatinnými.
3:2 = 1(zvyšok 1)
Teda 3:2*(3-1)=2 a mali by sme ešte pripočítať zvyšok po delení, teda 1.
Joker
Profil
SeparateSK:
To je ovšem dost …neortodoxní… použití matematiky.
_es
Profil
Jan Tvrdík:
Tak nějak nechápu, proč mi to vysvětlujete.
Je to dotaz v sekcii JavaScript, teda ide o dvojitú presnosť v norme IEEE_754. Tam by nemal byť rozdiel vo výsledku v tebou uvedených výrazoch. Príklad v [#2] ukazuje len na hranice použitého formátu čísel, trebárs upper v skutočnosti nie je 9 876 543 210 000 099 ale 9 876 543 210 000 100.
Joker
Profil
Chamurappi:
Ano, ale vyhnat mantinely cyklu do takových výšin obvykle postrádá smysl.
Nepodceňuj borce, kteří jsou schopní takhle pracovat s telefonními čísly a podobně ;-)

Je pravda, že mě napadl jen jeden běžně používaný identifikátor, který by mohl dosáhnout tak vysoké hodnoty: Číslo platební karty.
Pokud by začínalo 9, což není případ běžně dostupných platebních karet.
Ale použitím něčeho takového by možná té situace dosáhnout šlo.
TomasJ
Profil
Já jsem nepřesnost výsledků, jak mnoho píšících v tomto vláknu, řešil zaokrouhlováním.
Sestavil jsem si jednoduchou funkci. Neřeší nepřesnost v případě, že chci všechna čísla (v tomto případě 14) za desetinnou čárkou. Funkce vypadala nějak takto:
var x = 15.8;
var y = 156.8;

function zaokrouhli(cislo, pocetMist){
    if(pocetMist > 0) {
        var exp = Math.pow(10, pocetMist);
        cislo = Math.round(cislo * exp);
        return cislo / exp; 
    }
    else return Math.round(cislo);
}

alert(zaokrouhli(x+y,10));
Tím samozřejmě nechci říci, že je nejlepší na světě, a že právě tuto má někdo používat. Jen ukazuji, jak jsem to řešil já :)
I když kompletně neřeší daný problém.
_es
Profil
TomasJ:
function zaokrouhli(cislo, pocetMist=0){
To snáď vyvolá syntaktickú chybu - až na niektoré prehliadače.
TomasJ
Profil
Tak jasné to = 0 by se správně mělo nastavit až ve funkci, nebo vůbec.
* Dík za poznámku, upravil jsem to.
« 1 2

Vaše odpověď

Mohlo by se hodit

Neumíte-li správně určit příčinu chyby, vkládejte odkazy na živé ukázky.
Užíváte-li nějakou cizí knihovnu, ukažte odpovídajícím, kde jste ji vzali.

Užitečné odkazy:

Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm:

0