Hlavní navigace

Programovací jazyk Julia: funkce jako základní stavební prvek programů

Pavel Tišnovský 7. 6. 2016

Ve třetím článku o jazyce Julia se budeme zabývat funkcemi, které v tomto jazyce tvoří základní stavební prvek všech programů. Samozřejmě si popíšeme i některé vestavěné funkce vyššího řádu.

Obsah

1. Programovací jazyk Julia: funkce jako základní stavební prvek programů

2. Běžné funkce

3. Zkrácený zápis funkce

4. Anonymní funkce

5. Numerický výpočet určitého integrálu

6. Funkce s větším množstvím návratových hodnot

7. Funkce s proměnným počtem argumentů (variadické funkce)

8. Funkce s volitelnými argumenty

9. Funkce s pojmenovanými argumenty (keyword arguments)

10. Operátory jsou jen jinak zapisované funkce

11. Jména funkcí pro speciální operátory

12. Funkce vyššího řádu: map a pmap

13. Další užitečné funkce vyššího řádu reduce, foldlfoldr

14. Speciální varianty reduce: maximum, minimumsum

15. Predikáty any a all

16. Odkazy na Internetu

1. Programovací jazyk Julia: funkce jako základní stavební prvek programů

Základní informace o použití funkcí v programovacím jazyku Julia jsme si již řekli v prvníve druhé části tohoto seriálu, ovšem vzhledem k tomu, že funkce (a taktéž operátory, což jsou ve skutečnosti jen odlišně zapisované funkce) mají v tomto jazyku význam základního stavebního prvku, se jimi dnes budeme zabývat podrobněji. Nezapomeneme samozřejmě ani na použití anonymních funkcí, především v souvislosti s funkcemi vyššího řádu. Programovací jazyk Julia totiž přebírá mnoho svých vlastností z klasických funkcionálních jazyků, takže v něm nalezneme jak základní funkce vyššího řádu typu map (i její paralelní verze pmap), apply, reduce (specifikované přesněji ve dvojici foldl a foldr), tak i různé další funkce, které jako svůj parametr akceptují jiné funkce. Příkladem může být funkce nazvaná quadgk určená pro numerickou integraci libovolné funkce, která je do quadgk předána.

2. Běžné funkce

Běžný zápis funkce vypadá velmi jednoduše a do značné míry se podobá zápisu funkce v programovacím jazyku Lua: definice funkce začíná klíčovým slovem function, za nímž následuje jméno funkce se seznamem parametrů umístěných v závorce. Po této hlavičce je možné zapsat libovolné množství příkazů tvořících tělo funkce, přičemž na libovolném místě lze v případě potřeby použít příkaz return pro ukončení funkce a pro vrácení návratové hodnoty či hodnot. Celá definice funkce končí klíčovým slovem end. Typickým příkladem je uživatelská funkce určená pro součin dvou hodnot:

function mul(x,y)
    return x*y;
end

Ve skutečnosti není středník důležitý, takže ho lze vynechat:

function mul(x,y)
    return x*y
end

V tomto případě je možné klíčové slovo return vynechat, protože hodnota posledního příkazu či výrazu se automaticky považuje i za návratovou hodnotu funkce:

function mul(x,y)
    x*y;
end

Opět je možné vynechat přebytečný středník:

function mul(x,y)
    x*y
end

Z předchozí části tohoto seriálu ovšem již víme, že se funkce mohou skládat z metod, přičemž se jednotlivé metody od sebe odlišují typem parametrů. To mj. znamená, že funkci mul (resp. jednu její metodu) můžeme napsat i takto:

function mul(x::Number, y::Number)
    x*y
end

Navíc můžeme k výše zapsané metodě akceptující jako své parametry dvojici čísel libovolného typu přidat i metodu určenou pro výpočet skalárního součinu dvou vektorů (opět pro zjednodušení vynecháme klíčové slovo return):

function mul(x::Array{Int,1}, y::Array{Int,1})
    vecdot(x,y)
end

Poznámka: zápis Array{Int,1} popisuje pole s jednou dimenzí (tedy vektor) s prvky typu Int. Ovšem samotný typ Int je ve skutečnosti abstraktním typem a může značit konkrétní typ Int8, Int16, Int32 atd. až Int128.

Obě dvě metody tvořící dohromady funkci mul si můžeme velmi snadno otestovat:

julia> mul(6,7)
42
 
julia> mul([1,2], [1,2])
5
 
julia> mul([1,2,3], [1,2,3])
14
 
julia> mul([1,2,3], [1,2])
ERROR: DimensionMismatch("vector x has length 3, but vector y has length 2")
 in vecdot at linalg/generic.jl:248
 in mul at none:2

V posledním kroku vidíme, že se nepodařilo vynásobit dva vektory s různou délkou (což je pochopitelná vlastnost).

3. Zkrácený zápis funkce

Kromě definice uživatelských funkcí, s nímž jsme se seznámili v předchozí kapitole, podporuje programovací jazyk Julia i alternativní „jednořádkový“ způsob zápisu. Tento způsob se typicky používá ve chvíli, kdy je tělo funkce skutečně jednoduché, protože pro delší či složitější funkce se zápis na jediném řádku stává dosti nepřehledným. Tento způsob se nejvíce podobá matematickému zápisu funkcí a je pro něj typické vynechání klíčových slov function a end:

julia> f(x,y) = x+y
f (generic function with 1 method)

Naši demonstrační funkci pro vynásobení dvou hodnot lze přepsat i takto:

julia> mul(x,y)=x*y
mul (generic function with 1 method)
 
julia> mul(6,7)
42

U tohoto zápisu se můžeme často setkat s použitím ternárního operátoru:

julia> max2(x,y) = x>y ? x : y
max2 (generic function with 1 method)
 
julia> max2(1,2)
2
 
julia> max2(2,1)
2

Zápis s použitím konstrukce if-then-else vypadá takto:

julia> max2(x,y) = if x > y x else y end
max2 (generic function with 1 method)
 
julia> max2(1,2)
2
 
julia> max2(2,1)
2

4. Anonymní funkce

Programovací jazyk Julia podporuje i tvorbu takzvaných anonymních funkcí, což jsou funkce (programový kód, který lze zavolat), kterým není přiřazeno jméno. Předností takových funkcí je především sevřený styl zápisu, v němž se nepoužívají klíčová slova function a end, ale (alespoň většinou) výraz či výrazy představující nějaký výpočet na základě parametrů předaných anonymní funkci. Definici anonymní funkce tak lze použít například i jako parametr jiné funkce (funkce vyššího řádu). Při definici anonymních funkcí se používá dvojznak ->, před nějž se zapisuje parametr či parametry a za něj výraz, jehož vypočtený výsledek je současně návratovou hodnotou anonymní funkce. Nejprve se podívejme na jednoduchou anonymní funkci s jediným parametrem:

julia> x -> x+1
(anonymous function)

Funkce se dvěma parametry vypadá takto:

julia> (x,y) -> x+y
(anonymous function)

Podobným způsobem lze samozřejmě definovat i funkce s vyšším počtem parametrů.

5. Numerický výpočet určitého integrálu

Podívejme se nyní na praktický příklad použití anonymních funkcí, a to konkrétně při výpočtu určitého integrálu. Pro podobné výpočty sice existují specializované knihovny (z nichž naprostou většinou lze z jazyka Julia volat), ovšem pro jednodušší účely může postačit použít funkci nazvanou quadgk(), která je dostupná i v případě, že použijeme pouze základní balíčky (knihovny) programovacího jazyka Julia. Podívejme se, jak lze vypočítat určitý integrál goniometrické funkce sinus pro meze 0 až π. Funkce quadgk() je funkce vyššího řádu, protože jako svůj první parametr akceptuje jinou funkci, konkrétně funkci, jejíž faktoriál budeme počítat:

julia> quadgk(sin, 0, pi)
(2.0,1.7905676941154525e-12)

Výsledkem je hodnota určitého integrálu (plocha pod křivkou) a předpokládaná absolutní chyba.

Pokud budeme chtít použít uživatelské funkce, máme dvě možnosti. Buď tyto funkce definovat a pojmenovat (viz druhou kapitolu), což si vyžádá určitý prostor ve zdrojovém kódu, nebo můžeme použít funkce anonymní. Vypočtěme například plochu obdélníku 10×1 jednotka (anonymní funkce ignoruje svůj parametr):

julia> quadgk(x->1, 0, 10)
(10.0,0.0)

Plocha pod křivkou y=x pro různé meze:

julia> quadgk(x->x, 0, 1)
(0.5,0.0)
 
julia> quadgk(x->x, -10, 10)
(0.0,0.0)

Plocha pod křivkou y=x x:

julia> quadgk(x->x^x, 0, 1)
(0.7834305106229384,4.864047851993458e-9)
 

atd.

6. Funkce s větším množstvím návratových hodnot

Někteří čtenáři si možná už povšimli, že se programovací jazyk Julia v mnoha ohledech podobá jazyku Lua (což není náhoda). Týká se to i další užitečné vlastnosti – funkce totiž nemusí vracet jen jednu hodnotu, ale (prakticky) libovolný počet hodnot. Pokud potřebujete vrátit například dvě hodnoty, lze za klíčové slovo return zadat dva výrazy, které jsou od sebe oddělené čárkou. Příkladem může být funkce swap() akceptující dva parametry a vracející vyhodnocené parametry v opačném pořadí:

julia> function swap(x,y)
       return y,x
       end
swap (generic function with 1 method)

Při volání této funkce v interaktivním vývojovém prostředí ihned obě vrácené hodnoty uvidíme na obrazovce (budou zobrazeny v kulatých závorkách):

julia> swap(1,2)
(2,1)

Příkladem může být například uživatelská funkce nazvaná minmax(), která pro předané pole nalezne jeho minimální a maximální prvek. Oba tyto prvky vrátí volajícímu programovému kódu:

julia> function minmax(array)
       return minimum(array), maximum(array)
       end
minmax (generic function with 1 method)

Vyzkoušení této funkce je snadné a přímočaré:

julia> minmax([1,2,3,4,3,2,1])
(1,4)

Poznámka: i výše popsaná funkce quadgk() určená pro numerickou integraci vracela dvě hodnoty: výsledek vlastního výpočtu (plochu pod křivkou) a absolutní chybu (resp. přesněji řečeno odhad chyby).

7. Funkce s proměnným počtem argumentů (variadické funkce)

V některých případech může být užitečné použít funkci či funkce s proměnným počtem argumentů. Tyto funkce se někdy nazývají variadické funkce a poznáme je podle toho, že se v seznamu parametrů v definici funkce nachází jméno argumentu následované třemi tečkami. Všechny další parametry se předají ve formě sekvence, kterou je samozřejmě možné zpracovat, přičemž je nutné mít na paměti, že tato sekvence může být i prázdná. Podívejme se na jednoduchý příklad – funkci pro výpočet sumy všech svých parametrů:

function suma(x...)
    local result = 0
    for item in x
        result = result + item
    end
    result
end

Funkci si ihned otestujme, a to i pro volání bez parametrů:

julia> suma()
0
 
julia> suma(1)
1
 
julia> suma(1,2)
3
 
julia> suma(1,2,3)
6
 
julia> suma(1,2,3,4, 1//2)
21//2

Nepovinné parametry lze zkombinovat s parametry povinnými, pouze je zapotřebí dodržet pravidlo, že nepovinné parametry se uvádí až za všemi parametry povinnými:

function scaled_suma(scale, x...)
    local result = 0
    for item in x
        result = result + item
    end
    scale*result
end

Nyní je první parametr povinný, o čemž se lze snadno přesvědčit:

julia> scaled_suma()
ERROR: MethodError: `scaled_suma` has no method matching scaled_suma()
 
julia> scaled_suma(1)
0
 
julia> scaled_suma(2, 1)
2
 
julia> scaled_suma(2, 1, 2, 3)
12

8. Funkce s volitelnými argumenty

Programovací jazyk Julia podporuje i práci s volitelnými argumenty. Pokud nejsou tyto argumenty naplněny při volání funkce, použije se jejich implicitní hodnota zadaná již v definici funkce. Díky podpoře funkcí s volitelnými argumenty tak nemusíme vytvářet metody se stejným jménem, ale s proměnným počtem parametrů (což je sice ekvivalentní, ale mnohdy zbytečně složité). Samozřejmě si opět ukážeme demonstrační příklad:

julia> function add(x, y=0, z=0)
       x+y+z
       end
add (generic function with 3 methods)
 
julia> add()
ERROR: MethodError: `add` has no method matching add()
 
julia> add(1)
1
 
julia> add(1,2)
3
 
julia> add(1,2,3)
6

9. Funkce s pojmenovanými argumenty (keyword arguments)

Poslední variantou funkcí jsou funkce s pojmenovanými argumenty. Aby interpret tyto argumenty korektně rozeznal, musíme pro jejich oddělení od běžných argumentů použít středník a nikoli pouze čárku:

function area(message; width=0, height=0)
    print(message)
    width*height
end

Povšimněte si, že v tomto případě je nutné uvést výchozí hodnotu argumentů.

Při volání takové funkce se explicitně uvedou jména pojmenovaných argumentů:

julia> area("Plocha obdelniku ")
Plocha obdelniku 0
 
julia> area("Plocha ctverce ", width=2, height=2)
Plocha ctverce 4
 
julia> area("Plocha obdelniku ", width=10, height=1)
Plocha obdelniku 10

Díky podpoře pro pojmenované parametry lze vytvářet čitelné volání funkcí, typicky funkcí pro vykreslování grafů (specifikace stylu vykreslování) apod.

10. Operátory jsou jen jinak zapisované funkce

Již v úvodním článku jsme si řekli, že ve skutečnosti jsou všechny aritmetické operátory (součet, rozdíl, součin, podíl atd.) implementovány běžnými funkcemi pojmenovanými stejným znakem, jaký odpovídá danému operátoru. To například znamená, že součet dvou čísel lze zapsat jako 1+2, ale také formou funkce +(1,2), což je sice možná poněkud podivné, ale ve skutečnosti užitečné, protože takto zapsaný operátor má volitelnou aritu (počet operandů). Ovšem současně to také znamená, že můžeme například definovat metodu + pro nový uživatelsky definovaný datový typ a tak vlastně operátor „přetížit“ (což je chování, které známe prakticky ze všech programovacích jazyků, i když u některých z nich je přetížení součástí standardu jazyka a není přístupné uživatelům). Aby bylo chování konzistentní, je nutné takovou metodu vytvořit s variadickým počtem parametrů.

11. Jména funkcí pro speciální operátory

Kromě jmen základních funkcí +, -, *, /, % a ^ představujících aritmetické operátory se můžeme setkat s následujícími funkcemi, které syntakticky nahrazují své operátory (to tedy znamená, že následující operátory nelze použít jako přímé jméno funkce, protože by to syntakticky nedávalo smysl):

Zápis Volá se funkce/metoda
[A B C …] hcat()
[A, B, C, …] vcat()
[A B; C D; …] hvcat()
A' ctranspose()
A.' transpose()
1:n colon()
A[i] getindex()
A[i]=x setindex!()
A(x) call()

Pokud tedy potřebujete přetížit příslušný operátor, je nutné ve skutečnosti definovat příslušnou metodu hcat, vcat, call atd.

12. Funkce vyššího řádu: map a pmap

Zajímavé a užitečné je použití takzvaných funkcí vyššího řádu. Jedná se o funkce, které jako svůj parametr (parametry) akceptují jiné funkce popř. nějaké funkce vrací. My jsme se již s jednou podobnou funkcí setkali – jednalo se o knihovní funkci quadgk() určenou pro numerickou integraci. Ovšem ve standardní knihovně nalezneme i další užitečné funkce vyššího řádu. Programátoři používající nějaký funkcionální jazyk pravděpodobně znají funkci map určenou pro aplikaci nějaké jiné funkce na prvky sekvence, seznamu či pole. Tuto funkci vyššího řádu pochopitelně nalezneme i v programovacím jazyku Julia, takže se podívejme na možnosti jejího použití.

Definujme uživatelskou funkci pro výpočet binomických koeficientů (kombinačních čísel) „n nad k“:

function binom(n,k)
    n >= k || return 0
    n == 1 && return 1
    k == 0 && return 1
    (n * binom(n - 1, k - 1)) ÷ k
end

Pokud nyní budeme chtít vypočítat šestý řádek Pascalova trojúhelníku, není nic snadnějšího:

julia> map(x->binom(5,x), 0:5)
 
6-element Array{Int64,1}:
  1
  5
 10
 10
  5
  1

Podobně můžeme vypočítat desátý řádek Pascalova trojúhelníku:

julia> map(x->binom(10,x) ,0:10)
 
11-element Array{Int64,1}:
   1
  10
  45
 120
 210
 252
 210
 120
  45
  10
   1

V jazyku Julia nalezneme i paralelní variantu funkce map, která se jmenuje pmap. Aby bylo možné tuto variantu efektivně využít, je nutné společně s interpretrem spustit i větší množství tzv. workerů, a to zadáním parametru -p n, kde n je počet workerů (nastavit lze například na počet jader). Dále je nutné, aby funkce, která se má počítat paralelně, byla dostupná všem workerům, což zajistí makro @everywhere. Vyzkoušejme si například paralelní výpočet Ackermannovy funkce, protože vyhodnocení této funkce je i přes její jednoduchý zápis poměrně zdlouhavé (a taktéž náročné na kapacitu zásobníku):

@everywhere(function ackermann(m,n)
    if m == 0
        return n + 1
    elseif n == 0
        return ack(m-1,1)
    else
        return ack(m-1,ack(m,n-1))
    end
end)

Sériový výpočet hodnot Ackermannovy funkce pro parametry [4,1], [4,2], [4,3] a [4,4] bude vypadat takto:

map(x->ackermann(4,x), 1:4)

Obrázek 1: Sériový výpočet hodnot Ackermannovy funkce. Procesor se „fláká“ na pouhé čtvrtině jeho skutečného výkonu.

Po spuštění interpretru a čtyř workerů příkazem…

julia -p 4

…je již možné použít paralelní verzi funkce map:

pmap(x->ackermann(4,x), 1:4)

Obrázek 2: Paralelní výpočet hodnot Ackermannovy funkce. Povšimněte si paralelně pracujících workerů a vytížení procesoru.

13. Další užitečné funkce vyššího řádu reduce, foldlfoldr

Další známou funkcí vyššího řádu, kterou nalezneme v prakticky každém funkcionálním jazyce, je funkce nazvaná reduce, která slouží pro postupné zpracování vstupní sekvence po jednotlivých prvcích. Pokud použijeme binární operátor, aplikuje se na první dva prvky v sekvenci, následně se aplikuje na výsledek této operace společně se třetím prvkem atd. Určitým problémem je, že u funkce reduce není předepsáno, zda se sekvence bude zpracovávat od začátku či od konce, takže se v programovacím jazyku Julia vyskytují další dvě funkce vyššího řádu nazvané foldl a foldr, u nichž je směr zpracování sekvence pevně zadaný (což ale může znamenat určité zpomalení). U některých operací směr zpracování nehraje žádnou roli (komutativita):

julia> reduce(*, 1:10)
3628800
 
julia> foldl(*, 1:10)
3628800
 
julia> foldr(*, 1:10)
3628800

Ovšem u dalších operací se již výsledky mohou lišit:

julia> reduce(/, [1,2,3])
0.16666666666666666
 
julia> foldl(/, [1,2,3])
0.16666666666666666
 
julia> foldr(/, [1,2,3])
1.5

Zde mimochodem můžeme vidět, že v tomto konkrétním případě se funkce reduce chová stejně jako funkce foldl, tj. „redukuje“ vstupní sekvenci od začátku směrem ke konci.

14. Speciální varianty reduce: maximum, minimumsum

Výše popsanou funkci vyššího řádu reduce, popř. její konkrétnější varianty foldl a foldl, je možné použít pro implementaci mnoha dalších užitečných funkcí. Příkladem může být funkce pro výpočet maximálního prvku v poli. Tuto funkci lze definovat následovně:

function maximum_impl(array)
    reduce((x,y) -> x>y ? x:y, array)
end
 
maximum_impl([4,3,2,1])
4

Vidíme zde použití anonymní funkce akceptující dva parametry a vracející větší z těchto parametrů (je zde použit ternární operátor, který umožňuje tělo anonymní funkce zapsat jediným výrazem).

Ovšem vzhledem k tomu, že podobné funkce potřebujeme v programech používat velmi často, obsahuje již základní knihovna jazyka Julia jejich optimalizované verze. Podívejme se na demonstrační příklady – budeme počítat maximální a minimální hodnotu pole s výsledkem výpočtu binomických koeficientů „deset nad k“. Navíc ještě spočítáme součet všech těchto koeficientů:

function binom(n,k)
    n >= k || return 0
    n == 1 && return 1
    k == 0 && return 1
    (n * binom(n - 1, k - 1)) ÷ k
end
 
b=map(x->binom(10,x),0:10)
 
11-element Array{Int64,1}:
   1
  10
  45
 120
 210
 252
 210
 120
  45
  10
   1

Pole s vypočtenými prvky máme připraveno, takže ho ihned můžeme použít:

julia> minimum(b)
1
 
julia> maximum(b)
252
 
julia> sum(b)
1024

Poznámka: kromě výše uvedených funkcí minimum(), maximum() a sum() nalezneme ve standardní knihovně programovacího jazyka Julia i další užitečné funkce pracující s celým polem či sekvencí hodnot. Příkladem může být funkce prod() pracující podobně jako sum(), ovšem prvky předaného pole jsou vynásobeny a nikoli sečteny:

julia> prod([1,2,3])
6
 
julia> prod(1:10)
3628800

15. Predikáty any a all

Do stejné kategorie, jako výše zmíněné funkce, patří i takzvané predikáty, tj. funkce vracející pravdivostní hodnotu true nebo false na základě předaných parametrů. Zajímat nás nyní budou dva predikáty nazvané any a all. Predikát any vrací pravdivostní hodnotu true ve chvíli, kdy alespoň jeden prvek pole (či sekvence) splňuje zapsanou podmínku. Tuto podmínku je možné při volání predikátu zapsat například formou anonymní funkce, takže celé vyhodnocení predikátu je možné provést na jediném řádku ve zdrojovém kódu. Nejprve si připravme pole, jehož prvky budeme zkoumat:

julia> b=map(x->binom(10,x), 0:10)
11-element Array{Int64,1}:
   1
  10
  45
 120
 210
 252
 210
 120
  45
  10
   1

Nyní již můžeme zjistit informace o celém poli, například existenci prvku většího než 200 či naopak alespoň jednoho záporného prvku:

julia> any(x -> x>200, b)
true
 
julia> any(x -> x<0, b)
false

Naproti tomu predikát nazvaný all vrací pravdivostní hodnotu true pouze tehdy, když je zadaná podmínka platná pro všechny prvky pole či sekvence. V opačném případě, tedy pokud alespoň jeden prvek podmínku nesplňuje, pochopitelně vrací false:

julia> all(x -> x>200, b)
false
 
julia> all(x -> x>0, b)
true

16. Odkazy na Internetu

  1. Introducing Julia/Functions
    https://en.wikibooks.org/wi­ki/Introducing_Julia/Functi­ons
  2. Functions (Julia documentation)
    http://docs.julialang.org/en/release-0.4/manual/functions/
  3. Evaluate binomial coefficients
    http://rosettacode.org/wi­ki/Evaluate_binomial_coef­ficients
  4. Ackermann function
    http://rosettacode.org/wi­ki/Ackermann_function
  5. Julia (front page)
    http://julialang.org/
  6. Julia – dokumentace
    http://docs.julialang.org/en/release-0.4/
  7. Julia – repositář na GitHubu
    https://github.com/JuliaLang/julia
  8. Julia (programming language)
    https://en.wikipedia.org/wi­ki/Julia_%28programming_lan­guage%29
  9. IJulia
    https://github.com/JuliaLan­g/IJulia.jl
  10. Introducing Julia
    https://en.wikibooks.org/wi­ki/Introducing_Julia
  11. Julia: the REPL
    https://en.wikibooks.org/wi­ki/Introducing_Julia/The_REPL
  12. Introducing Julia/Metaprogramming
    https://en.wikibooks.org/wi­ki/Introducing_Julia/Meta­programming
  13. Month of Julia
    https://github.com/DataWo­okie/MonthOfJulia
  14. Learn X in Y minutes (where X=Julia)
    https://learnxinyminutes.com/doc­s/julia/
  15. New Julia language seeks to be the C for scientists
    http://www.infoworld.com/ar­ticle/2616709/application-development/new-julia-language-seeks-to-be-the-c-for-scientists.html
  16. Julia: A Fast Dynamic Language for Technical Computing
    http://karpinski.org/publi­cations/2012/julia-a-fast-dynamic-language
  17. The LLVM Compiler Infrastructure
    http://llvm.org/
  18. Julia: benchmarks
    http://julialang.org/benchmarks/
  19. Type system
    https://en.wikipedia.org/wi­ki/Type_system
  20. Half-precision floating-point format
    https://en.wikipedia.org/wiki/Half-precision_floating-point_format
Našli jste v článku chybu?

13. 6. 2016 23:50

Ignac (neregistrovaný)

Ta Julia je bomba. Ani sa mi nechce vracat k Matlabu :)

Podnikatel.cz: Vládu obejde, kvůli EET rovnou do sněmovny

Vládu obejde, kvůli EET rovnou do sněmovny

Vitalia.cz: „Připluly“ z Německa a možná obsahují jed

„Připluly“ z Německa a možná obsahují jed

DigiZone.cz: Česká televize mění schéma ČT :D

Česká televize mění schéma ČT :D

Vitalia.cz: Říká amoleta - a myslí palačinka

Říká amoleta - a myslí palačinka

Podnikatel.cz: Přehledná titulka, průvodci, responzivita

Přehledná titulka, průvodci, responzivita

Měšec.cz: Jak vymáhat výživné zadarmo?

Jak vymáhat výživné zadarmo?

Podnikatel.cz: Na poslední chvíli šokuje vyjímkami v EET

Na poslední chvíli šokuje vyjímkami v EET

Vitalia.cz: Láska na vozíku: Přitažliví jsme pro tzv. pečovatelky

Láska na vozíku: Přitažliví jsme pro tzv. pečovatelky

Vitalia.cz: Baletky propagují zdravotní superpostel

Baletky propagují zdravotní superpostel

120na80.cz: Bojíte se encefalitidy?

Bojíte se encefalitidy?

Lupa.cz: UX přestává pro firmy být magie

UX přestává pro firmy být magie

Vitalia.cz: Jsou čajové sáčky toxické?

Jsou čajové sáčky toxické?

Lupa.cz: Avast po spojení s AVG propustí 700 lidí

Avast po spojení s AVG propustí 700 lidí

Měšec.cz: U levneELEKTRO.cz už reklamaci nevyřídíte

U levneELEKTRO.cz už reklamaci nevyřídíte

DigiZone.cz: NG natáčí v Praze seriál o Einsteinovi

NG natáčí v Praze seriál o Einsteinovi

120na80.cz: Rakovina oka. Jak ji poznáte?

Rakovina oka. Jak ji poznáte?

DigiZone.cz: Sony KD-55XD8005 s Android 6.0

Sony KD-55XD8005 s Android 6.0

Podnikatel.cz: EET: Totálně nezvládli metodologii projektu

EET: Totálně nezvládli metodologii projektu

Lupa.cz: Proč firmy málo chrání data? Chovají se logicky

Proč firmy málo chrání data? Chovají se logicky

Vitalia.cz: Chtějí si léčit kvasinky. Lék je jen v Německu

Chtějí si léčit kvasinky. Lék je jen v Německu