Autor Zpráva
oxidián
Profil *
Nevíte jaký je zdrojový kód pro funkci round? Zajímá mě jakým způsobem lze dělit s přesností na dvě nebo na tři místa.
Yuff.3
Profil
Mám taký pocit, že toto popísal aj djmetla vo svojom videu - nájdeš to na google - neviem či by sa to nebralo ako reklama preto sem nedávam presný link.
smitka
Profil
A/B na 2 místa:

intval( (A+0.5) *10 / B ) /10

A/B na 3 místa:

intval( (A+0.5) *100 / B ) /100
oxidián
Profil *
Yuff.3:
To video bylo kde na youtube? Co mám hledat? "djmetla video round php" mi nic nedává

smitka
co je B?
Yuff.3
Profil
skús len djmetla (eu) a v serialoch nájdi video - má tam len jedno v ktorom sa zaoberá php - základy php
oxidián
Profil *
Tak jo shledl jsem video, malem sem z toho oslepl ale dobre, no aspon už umím nastavit ptoměnnou a spočítat $a+$b. To co chci tam ale není
smitka
Profil
oxidián:
B je dělitel

10/6

intval(10+0,5)*10/6)/10
intval(105/6)/10
intval(17,777)/10
17/10 = 1,7
Alphard
Profil
Aneb jak to zkomplikovat co nejvíc. Na tohle má funkce round() druhý parametr.
smitka
Profil
Alphard:
Tak otázka byla na zdrojový kód zaokrouhlování a toto je jeden z možných alogoritmů - přičítání 0.5 se reálně používá. Předpokládám, že dokumentaci k funkci v php si zvládne přečíst každý.
Alphard
Profil
smitka:
Předpokládám, že dokumentaci k funkci v php si zvládne přečíst každý.
Je to smutné, ale velká část dotazů na tomto fóru by se vyřešila přečtením dokumentace. Doporučuji spíš přístup snažit se z dotazu odhadnout reálný problém a pomoct ho řešit, není třeba tazatele podporovat ve špatný řešeních.
oxidián
Profil *
smitka:
vůbec tě nechápu. Jaký dělitel? Syntaxe round:

float round ( float $val [, int $precision = 0 [, int $mode = PHP_ROUND_HALF_UP ]] )

Kde máš $val a kde máš $precision v tom tvém kódu? Dělitel v syntaxi není.
smitka
Profil
Alphard:
Máš pravdu, šel jsem přímo k problému - dělit 2 čísla na určený počet desetinných míst.

oxidián:

Dával jsem do příkladu dělení 2 čísel (jako zlomek) na x desetinných míst, jak ses ptal - musíš dělit A/B => dělenec dělitelem.

Pokud chceš přímo zaokrouhlování $val (desetinné číslo) na $precision míst, tak:

$x = 10^$precision;//10,100,...
intval( $val * $x + 0.5) / $x

např. 1.666666 na 1 místo

intval( 1.666666 * 10 + 0.5) / 10
intval( 17.16666 ) / 10
17 / 10 = 1,7
Jan Tvrdík
Profil
smitka:
Pozor na to, že ^ v PHP není umocnění, ale bitový XOR. Operátor umocnění je ** (dostupný od PHP 5.6).
oxidián
Profil *
Dobře tak už to chápu. Takže mi výjde číslo s jednou desetinnou čárkou, a pak to musím celé zopakovat bez desítky, abych dostal celé číslo.


dík


Ale můj počítač to stejně není schopen spočítat:
num = 254.454300;
mi vrátí 254.449997 hloupý počítač :-)
Alphard
Profil
Ach jo, zatím 15 příspěvků kvůli takové trivialitě.

oxidián:
echo round(254.454300, 2); // 254.45
Vyhovuje, nebo chcete něco jiného?

smitka [#12]:
Viz [#13] Jan Tvrdík, neber si to špatně, ale vymýšlet složitá řešení (i kdyby fungovala) tazatelům, kteří to evidentně nepochopí a blbě použijí, je k ničemu.

Nevíte jaký je zdrojový kód pro funkci round?
Zřejmě tento github.com/php/php-src/blob/fc33f52d8c25997dd0711de3e07d0dc260a18c11/ext/standard/math.c#L139 (nejsem si 100% jistý).
oxidián
Profil *
Už to je vyřešeno. Použil jsem smitkovo řešení ale s precision = 1; tedy bez dělení. Je to rychlejší. Mě šlo o to že jsem nechtěl použít funkci. Funkce volané zevnitř cyklu dost nepříjemně zpomalují běh programu. Celkem jsem odstranil 2 funkce na zaokrouhlování a výsledek byl dvounásobné ušetření času.
smitka
Profil
Alphard:
Tak tazatel tady evidentně pochopil o co jde, pokud jde o obyčejné zaokrouhlení, tak je mnohem rychlejší přičít 0.5 a oříznout desetinnou část - to mi nepřijde jako vymýšlení složitého řešení a je to princip, který se běžně používá, protože je velmi rychlý. Myslím, že programátor by tyto triky měl znát.

Jan Tvrdík:
Pravda, neuvědomil jsem si (pracuji ve více jazycích), naštěstí byl princip jasný. Díky za upozornění.

Vhodnější by tedy bylo:
$x=array(1,10,100,1000,10000,10000);
intval( $val * $x[$precision] + 0.5) / $x[$precision]


Jsem názoru, že nemusí být vždy dobré používat vestavěné univerzální funkce, když potřebuji konkrétní jednoduchou věc.

Mohl bych klidně napsat i do dělení a násobení pomocí bitových posunů a trochu sčítání/odčítání, což je opět velmi rychlé:

function deleno10($val) {
    $q = ($val >> 1) + ($val >> 2);
    $q = $q + ($q >> 4);
    $q = $q + ($q >> 8);
    $q = $q + ($q >> 16);
    $q = $q >> 3;
    $r = $val - ((($q << 2) + $q) << 1);
    return $q + ($r > 9);
}


function krat10($val){
    return ($val << 3) + ($val << 1);
}

Někdy může být ++i rychlejší než i++. Bohužel takové věci už dnes skoro nikdo neřeší, výkonu je prý dost...
Jan Tvrdík
Profil
smitka:
Řešit takové věci v PHP je dost zbytečné, tohle není C. Pokud potřebuješ řešit rozdíl mezi ++i a i++, tak sis vybral špatný jazyk.
smitka
Profil
Jan Tvrdík:
Neříkám, že toto řeším v PHP, říkám jen, že hlubší znalost toho jak funkce fungují dělá lepší programátory.
Alphard
Profil
smitka [#17]:
Uznávám, že v tomto případě to nakonec pomohlo a moje rada nebyla příliš přínosná. Ale objektivně, z příspěvků výše to nešlo předvídat a statisticky je přínosnější můj přístup.
Zapomněl jsem, že je to ten samý člověk, se kterým jsme před rokem řešili nějaké konvoluce obrazů. Za mnoho let zpátky si nevzpomínám na nikoho jiného, kdo by měl důvod zabývat se rychlostí round() (řešení s intval je rychlejší o 23 %). Samozřejmě už tehdy jsme mu říkali, že PHP na tohle není zrovna vhodný jazyk a stále si myslím, že by bylo lepší úsilí vynaložené na optimalizaci zaokrouhlování vynaložit do studia C, ale to je jeho věc.

Bohužel takové věci už dnes skoro nikdo neřeší, výkonu je prý dost...
Protože k tomu mají důvod, volání tvé superfunkce deleno10() je až 10x pomalejší než nativní dělení /. Taky se divím, že to lidé v PHP nepoužívají častěji.

Neříkám, že toto řeším v PHP, říkám jen, že hlubší znalost toho jak funkce fungují dělá lepší programátory.
To nikdo nerozporuje, jen tvrdíme, že ušetřit pár procent výkonu není to nejdůležitější.
Davex
Profil
smitka:
hlubší znalost toho jak funkce fungují dělá lepší programátory
To ano, ale většina programátorů nepotřebuje vědět jak to funguje, protože to za ně vyřešili jiní.

V C má optimalizaci dělení nebo násobení konstantou na starosti překladač, který to udělá mnohem lépe než by to udělala většina programátorů. Například k vynásobení deseti potřebuje pouze dvě instrukce ($x = $val + 4 * $val a $x + $x) a k vydělení deseti použije trik s násobením magickou konstantou a posunem (($val * 3435973837) >> 35).

K pomalosti tvých rozepsaných výpočtů se už vyjadřoval Alphard.
smitka
Profil
"Superfunkcí na dělení" jsem nechtěl demonstrovat nejrychlejší postup pro dělení, ale ukázat, že lze spousty úloh řešit jiným způsobem. Násobením a dělením pouze ukazuji, že lze tyto úlohy řešit i bez použití násobení a dělení, které jsou na některých platformách neporovnatelně náročnější než bitové posuny a sčítání.

Je pravda, že pro PHP vývojáře na x86 je to naprosto nezajímavé a offtopic. Omlouvám se za to.

Vaše odpověď

Mohlo by se hodit


Prosím používejte diakritiku a interpunkci.

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