abclinuxu.cz AbcLinuxu.cz itbiz.cz ITBiz.cz HDmag.cz HDmag.cz abcprace.cz AbcPráce.cz
Inzerujte na AbcPráce.cz od 950 Kč
Rozšířené hledání
×
    14.6. 12:11 | IT novinky

    Google Blog ČR informuje, že mobilní aplikaci Gemini a NotebookLM lze používat už také v Česku.

    Ladislav Hagara | Komentářů: 18
    14.6. 11:33 | Nová verze

    Byla vydána nová major verze 8 duálně licencovaného open source frameworku JUCE (Wikipedie, GitHub) pro vývoj multiplatformních audio aplikací.

    Ladislav Hagara | Komentářů: 0
    14.6. 11:11 | IT novinky

    Od 18. června bude možné předobjednat notebook DC-ROMA RISC-V LAPTOP II od společnosti DeepComputing s osmijádrovým 64-bit RISC-V AI CPU a s předinstalovaným Ubuntu.

    Ladislav Hagara | Komentářů: 2
    13.6. 23:55 | Nová verze

    Byla vydána verze 1.79.0 programovacího jazyka Rust (Wikipedie). Podrobnosti v poznámkách k vydání na GitHubu. Vyzkoušet Rust lze například na stránce Rust by Example.

    Ladislav Hagara | Komentářů: 0
    13.6. 14:33 | Zajímavý článek

    Byly zveřejněny výsledky průzkumu (infografika) mezi uživateli FreeBSD.

    Ladislav Hagara | Komentářů: 0
    13.6. 13:22 | IT novinky

    Na konferenci DevConf.CZ 2024 je na stánku Furi Labs prezentován linuxový telefon FuriPhone FLX1. Jeho cena 499 dolarů.

    Ladislav Hagara | Komentářů: 17
    13.6. 00:11 | Nová verze

    Bylo vydáno Eclipse IDE 2024-06 aneb Eclipse 4.32. Představení novinek tohoto integrovaného vývojového prostředí také na YouTube.

    Ladislav Hagara | Komentářů: 1
    12.6. 22:00 | Nová verze

    Proton, tj. fork Wine integrovaný v Steam Play a umožňující v Linuxu přímo ze Steamu hrát hry určené pouze pro Windows, byl vydán ve verzi 9.0-2 (𝕏). Přehled novinek se seznamem nově podporovaných her na GitHubu. Aktuální přehled her pro Windows běžících díky Protonu také na Linuxu na stránkách ProtonDB.

    Ladislav Hagara | Komentářů: 0
    12.6. 15:44 | Nová verze

    Po roce od vydání verze 15.5 bylo vydáno openSUSE Leap 15.6. Přehled novinek v nejnovější verzi této linuxové distribuce v oznámení o vydání a v poznámkách k vydání.

    Ladislav Hagara | Komentářů: 0
    12.6. 12:44 | Nová verze

    Byla vydána nová verze 256 správce systému a služeb systemd (GitHub). Nově mimo jiné s run0 jako alternativou k sudo.

    Ladislav Hagara | Komentářů: 24
    Rozcestník

    Podpora pro rozměrovou analýzu v programovacích jazycích

    25.4.2021 21:15 | Přečteno: 2556× | programování | Výběrový blog | poslední úprava: 25.4.2021 21:15

    Kdysi dávno jsem na root.cz četl článek o programovacím jazyku Ada, kde autor mimo jiné ukazoval, jak lze silný typový systém jazyka použít k tomu, aby za nás překladač hlídal fyzikální rozměr hodnot v programu podobně, jako jsme na to zvyklí u běžných datových typů. Nedávno jsem si na to znovu vzpomněl, chvíli si s tím hrál a v tomto zápisku dal dohromady triviální demonstraci současných možností podpory jednotek v jazycích Ada, F# a Python.

    Ada

    Demonstrace z toho článku o jazyku Ada vypadala nějak takto:

    type Metry is new Float;
    type Ctverecni_Metry is new Float;
    
    -- Přetížení operátoru násobení pro datový typ metry tak, aby vracel metry
    -- čtvereční.
    function "*" (Left, Right : Metry) return Ctverecni_Metry is
    begin
      return Ctverecni_Metry(Float(Left)*Float(Right));
      -- před násobením jsme přetypovali na float, abychom zabránili rekurzi
      -- takto donutíme překladač použít standardní násobení pro typ Float
    end;
    
    declare
      vyska : Metry := 10.0;
      sirka : Metry := 15.0;
      plocha_a : Ctverecni_Metry;
      plocha_b : Metry;
    begin
      plocha_a := vyska*sirka; -- tohle je ok
      plocha_b := vyska*sirka; -- zde nastane chyba prekladu
    end;

    Pamatuji si, že to na mě tenkrát udělalo dojem. Ale tehdy jsem moc programovacích jazyků neznal a ani jsem to dál nezkoumal. Na druhou stranu jsem si z toho taky mylně na chvíli odnesl dojem, že podobné věci jsou záležitostí silně typovaných a málo používaných jazyků jako Ada. Což ale není úplně přesné, jak si ještě ukážeme.

    Když jsem se k tomu teď ze zvědavosti vrátil a chtěl si to vyzkoušet (v repozitáři Fedory nebo Debianu lze najít balíček s GNU Ada překladačem GNAT), ukázalo se, že je třeba ten kód trochu vylepšit, aby to ve skutečnosti opravdu fungovalo. Což v tomto případě znamená, aby to šlo přeložit s chybou, která demonstruje, jak to hlídání jednotek pěkně funguje (-:

    procedure Example1 is
      type Meters is new Float;
      type Meters_Squared is new Float;
      function "*" (Left, Right : Meters) return Meters_Squared is
      begin
        return Meters_Squared(Float(Left)*Float(Right));
      end;
      function "*" (Left, Right : Meters) return Meters is abstract;
      len_a : Meters := 10.0;
      len_b : Meters := 15.0;
      surface : Meters_Squared;
      len_sum : Meters;
    begin
      len_sum := len_a + len_b; -- ok
      surface := len_a * len_b; -- ok
      len_sum := len_a * len_b; -- invalid
    end Example1;
    

    Když opominu uhlazení dělající z toho příkladu samostatný Ada program, bylo třeba přidat deklaraci function "*" (Left, Right : Meters) return Meters is abstract, která tuto variantu násobení zděděnou z typu Float potlačí. A překlad pak opravdu chybu v rozměru zachytí, i když ta chybová hláška vypadá trochu zvláštně (zkoušeno s gcc-gnat-10.2.1-9 na Fedoře 33):

    $ gnatmake -q example1.adb
    example.adb:16:20: expected type "Meters" defined at line 2
    example.adb:16:20: found type "Meters" defined at line 2
    gnatmake: "example.adb" compilation error

    Obecné modelování fyzikálních rozměrů tímto způsobem nemusí být zcela přímočaré ani praktické. I když jednodušší případy, kdy se obejdeme bez rozměrové analýzy, můžou fungovat pěkně, jak je vidět na příkladu práce s metry a mílemi z úvodního kurzu jazyka Ada.

    Pro jazyk Ada v přehledu metod rozměrové analýzy se dozvíme, že tohle bylo jasné už někdy v 80. letech, kdy se tento problém začal řešit. Např. N. H. Gehani v článku z roku 1985 popisuje použití typového systému s přetížením operátorů (podobně jako to dělá naše ukázka výše) a dochází k tomu, že to obecně nefunguje:

    Derived types only partially solve the problem of detecting the inconsistent usage of objects; some valid usages of objects are also not allowed. Moreover, the solution is inelegant and inconvenient to use.

    To vedlo k návrhu různých knihoven zavádějících datové struktury obsahující hodnotu spolu s jednotkou a funkce pro práci s nimi. A něco takového je možné implementovat v libovolném jazyce, i když konkrétní přístup a garance, co knihovna programátorovi dává, se můžou v závislosti na možnostech jazyka dost lišit.

    Překladač GNAT dnes implementuje systém pro kontrolu rozměrů veličin, který staví na tzv. Aspects ze standadru Ada 2012, a je doplněn knihovnou System.Dim.Mks s definicí základních fyzikálních jednotek dle SI.

    S použitím tohoto rozšíření by náš příklad vypadal takto:

    with System.Dim.Mks; use System.Dim.Mks;
    procedure Example2 is
      len_a : Length := 10.0*m;
      len_b : Length := 15.0*m;
      surface : Area;
      len_sum : Length;
    begin
      len_sum := len_a + len_b; -- ok
      surface := len_a * len_b; -- ok
      len_sum := len_a * len_b; -- invalid
    end Example2;
    

    A jak se můžeme přesvědčit, opravdu to funguje:

    $ gnatmake -q -gnat2012 example2.adb
    example2.adb:10:11: dimensions mismatch in assignment
    example2.adb:10:11: left-hand side has dimension [L]
    example2.adb:10:11: right-hand side has dimension [L**2]
    gnatmake: "example2.adb" compilation error

    Taková podpora jednotek je pak někde mezi implementací přímo v jazyce, a pouhou knihovnou.

    F#

    Jeden z mála programovacích jazyků s přímou podporou pro práci s jednotkami, o kterém jste možná už někdy slyšeli, je funkcionální jazyk F#. Typový systém tohoto jazyka totiž umožňuje s jednotkami přímo pracovat, takže např. typ float<m> reprezentuje desetinné číslo pro počet metrů, zatímco float je desetinné číslo bez jednotky. Popis jak to funguje najdete na stránce Units of measure.

    Předchozí příklad přepsaný do jazyka F# by vypadal nějak takto:

    [<Measure>] type m
    
    let len_a = 10.0<m>
    let len_b = 15.0<m>
    let len_sum : float<m>   = len_a + len_b // ok
    let surface : float<m^2> = len_a * len_b // ok
    let len_c   : float<m>   = len_a * len_b // invalid
    

    A když se jej pokusíme přeložit, skončíme na očekávané chybě v jednotkách:

    $ dotnet run
    /home/martin/projects/hello-fsharp/Program.fs(7,36): error FS0001: The unit of measure 'm' does not match the unit of measure 'm ^ 2' [/home/martin/projects/hello-fsharp/hello-fsharp.fsproj]
    
    The build failed. Fix the build errors and run again.

    Python

    Knihoven pro práci s jednotkami pro jazyk Python existuje hned několik (viz přehled Python modulů pro rozměrovou analýzu). Pro ukázku jsem zvolil knihovnu Pint, čímž ale nechci tvrdit, že jde o nejlepší nebo nejpopulárnější modul tohoto typu (ostatní knihovny jsem nezkoušel).

    Náš předchozí příklad musíme při převodu do pythonu trochu upravit. I když python typový systém má, proměnné nelze typ explicitně přiřadit, a navíc knihovna Pint typový systém pro reprezentaci jednotek stejně nepoužívá. Takže místo pokusu o přiřazení metrů čtverečních do proměnné s počtem metrů, zkusíme metry čtvereční s metry prostě sečíst:

    import pint
    
    ureg = pint.UnitRegistry()
    
    len_a = 10 * ureg.m
    len_b = 15 * ureg.m
    len_sum = len_a + len_b # ok
    surface = len_a * len_b # ok
    len_c = surface + len_b # invalid
    

    A vidíme, že při spuštění programu dostáváme očekávanou chybu:

    $ python example.py
    Traceback (most recent call last):
      File "/home/martin/tmp/example.py", line 9, in <module>
        len_c = surface + len_b
      File "/usr/lib/python3.9/site-packages/pint/quantity.py", line 1018, in __add__
        return self._add_sub(other, operator.add)
      File "/usr/lib/python3.9/site-packages/pint/quantity.py", line 110, in wrapped
        return f(self, *args, **kwargs)
      File "/usr/lib/python3.9/site-packages/pint/quantity.py", line 930, in _add_sub
        raise DimensionalityError(
    pint.errors.DimensionalityError: Cannot convert from 'meter ** 2' ([length] ** 2) to 'meter' ([length])

    Další rozdíl oproti předchozím příkladům pochopitelně je, že jde o běhovou chybu. Ale pokud vám záleží na odhalení těchto chyb už v době překladu, asi nebudete používat python.

    Ale i v jazyce jako python se imho může hodit, že vám počítač s jednotkami pomáhá:

    >>> import pint
    >>> ureg = pint.UnitRegistry()
    >>> current = (300 * ureg.watt) / (6 * ureg.volt)
    >>> current
    <Quantity(50.0, 'watt / volt')>
    >>> current.dimensionality
    <UnitsContainer({'[current]': 1})>
    >>> current.to_base_units()
    <Quantity(50.0, 'ampere')>
    >>> (current * 30 * ureg.minute).to(ureg.ampere*ureg.hour)
    <Quantity(25.0, 'ampere * hour')>

    A klepne vás přes prsty, pokud po něm chcete nesmysl:

    >>> (current * 30 * ureg.minute).to(ureg.watt*ureg.hour)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "/usr/lib/python3.9/site-packages/pint/quantity.py", line 605, in to
        magnitude = self._convert_magnitude_not_inplace(other, *contexts, **ctx_kwargs)
      File "/usr/lib/python3.9/site-packages/pint/quantity.py", line 554, in _convert_magnitude_not_inplace
        return self._REGISTRY.convert(self._magnitude, self._units, other)
      File "/usr/lib/python3.9/site-packages/pint/registry.py", line 944, in convert
        return self._convert(value, src, dst, inplace)
      File "/usr/lib/python3.9/site-packages/pint/registry.py", line 1804, in _convert
        return super()._convert(value, src, dst, inplace)
      File "/usr/lib/python3.9/site-packages/pint/registry.py", line 1410, in _convert
        return super()._convert(value, src, dst, inplace)
      File "/usr/lib/python3.9/site-packages/pint/registry.py", line 977, in _convert
        raise DimensionalityError(src, dst, src_dim, dst_dim)
    pint.errors.DimensionalityError: Cannot convert from 'minute * watt / volt' ([current] * [time]) to 'hour * watt' ([length] ** 2 * [mass] / [time] ** 2)

    (-:

    Závěr

    Pokud vás tohle téma zaujalo, doporučuji se podívat na článek Dimensional Analysis in Programming Languages, kde najdete rozsáhlý přehled implementací rozměrové analýzy v mnoha programovacích jazycích.

    A pokud nějakou knihovnu pro práci s jednotkami ve svém kódu používáte, dejte vědět v komentářích.

           

    Hodnocení: 100 %

            špatnédobré        

    Anketa

    Práci s jednotkami v nějakém programovacím jazyku jsem:
     (50 %)
     (9 %)
     (36 %)
     (5 %)
    Celkem 22 hlasů

    Tiskni Sdílej: Linkuj Jaggni to Vybrali.sme.sk Google Del.icio.us Facebook

    Komentáře

    Vložit další komentář

    26.4.2021 07:36 _
    Rozbalit Rozbalit vše Re: Podpora pro rozměrovou analýzu v programovacích jazycích
    Většinou na počítání, jak jinak ;-) Ale v kterem jayzku je ta kalkulačka napsaná fakt nevím.
    26.4.2021 12:29 OldFrog {Ondra Nemecek} | skóre: 36 | blog: Žabákův notes | Praha
    Rozbalit Rozbalit vše Re: Podpora pro rozměrovou analýzu v programovacích jazycích
    Hodně zajímavé... díky.
    -- OldFrog
    26.4.2021 13:51 Tomáš
    Rozbalit Rozbalit vše Re: Podpora pro rozměrovou analýzu v programovacích jazycích
    Pro mě to je novinka, díky za ni. Momentálně to nepoužiju, ale je dobré vědět, že něco takového existuje.
    Gréta avatar 26.4.2021 21:58 Gréta | skóre: 36 | blog: Grétin blogísek | 🇮🇱==❤️ , 🇵🇸==💩 , 🇪🇺==☭
    Rozbalit Rozbalit vše Re: Podpora pro rozměrovou analýzu v programovacích jazycích

    se muže hodit :D ;D

    27.4.2021 07:03 kotrcka | skóre: 23 | blog: Onééé 2 | Praha
    Rozbalit Rozbalit vše Re: Podpora pro rozměrovou analýzu v programovacích jazycích
    Na čo? Adventný kód tým nevyriešiš a ani na mimibazar sa to nehodí :-D
    Keďže tu účet nejde zrušiť, zmenil som si heslo na random a "zabudol ho".
    27.4.2021 19:15 OldFrog {Ondra Nemecek} | skóre: 36 | blog: Žabákův notes | Praha
    Rozbalit Rozbalit vše Re: Podpora pro rozměrovou analýzu v programovacích jazycích
    Hodí se to všude kde se počítá. Typicky tam, kde má výpočet nějaký vztah k reálnému světu (počty, balení, rozměry, hmotnosti, fyzikální vlastnosti, koordináty...) nebo kde se kladou extra podmínky k tomu, aby měl výpočet smysl. Je překvapivé, jak opomíjené to je téma. Dobrý typový systém by měl být standard, realite je ovšem jiná.

    V praxi se to dohání nejčastěji implementací pomocí knihoven - příklady: Geografická knihovna mi nedovolí sčítat zeměpisnou délku se šířkou a poskytne jakž takž nějakou záruku, že má prováděný výpočet reálný geografický smysl.

    Další příklad: Matematické knihovny pro počítání s určitou kategorií čísel, například BigDecimal nebo BigInteger. Sice nepohlídá jednotky, ale alespoň garantuje určité vlastnosti kladené na danou kategorii čísel. To samé knihovny pro komplexní čísla.
    -- OldFrog
    27.4.2021 20:59 Tomáš
    Rozbalit Rozbalit vše Re: Podpora pro rozměrovou analýzu v programovacích jazycích
    Taky záleží na tom, jak se to projeví na výkonu. Třeba v Pythonu se nám vyplácelo některé úkony řešit poněkud humpolácky manuálně, než to nechat na Pythonu. Nějaké počítání s jednotkami by nám to úplně zabilo.

    Taky je otázka, jak chytrá by taková knihovna mohla být. Třeba v geografických knihovnách je to samý sinus a kosinus, kde se dá nasekat plno chyb. Počítám, že tak chytré to asi nebude, aby to ohlídalo, že dosadím správný úhel.
    27.4.2021 21:47 marbu | skóre: 31 | blog: hromada | Brno
    Rozbalit Rozbalit vše Re: Podpora pro rozměrovou analýzu v programovacích jazycích
    Ideálně se to na výkonu neprojeví, viz ten příklad v Adě nebo F#, kde se ta kontrola se provede v rámci kompilace. Pro výpočty v Pythonu se často používá numpy, a i když ta knihovna pint podporu pro numpy má, nějaký další overhead tam určitě bude.
    There is no point in being so cool in a cold world.
    30.4.2021 09:15 Jindřich Makovička | skóre: 17
    Rozbalit Rozbalit vše Re: Podpora pro rozměrovou analýzu v programovacích jazycích
    Jinak C++ má boost::units, kde se taky všechno řeší při kompilaci. A std::chrono už zvládá časové jednotky taky obstojně.
    HO▽ORK△ avatar 28.4.2021 10:34 HO▽ORK△ | skóre: 4 | blog: HOVORKUV_CTVERECKOVANY_SVET_DO_KAZDE_DOMACNOSTI
    Rozbalit Rozbalit vše Re: Podpora pro rozměrovou analýzu v programovacích jazycích
    28.4.2021 16:24 marbu | skóre: 31 | blog: hromada | Brno
    Rozbalit Rozbalit vše Re: Podpora pro rozměrovou analýzu v programovacích jazycích
    Neřekl bych, že tu existuje něco jako limit na počet tučňáků nebo zákon o zachování jejich počtu, ale můžu se mýlit :)
    There is no point in being so cool in a cold world.
    28.4.2021 11:20 luky
    Rozbalit Rozbalit vše Re: Podpora pro rozměrovou analýzu v programovacích jazycích
    V C toto jde hlidat nastrojem sparse.

    Založit nové vláknoNahoru

    ISSN 1214-1267   www.czech-server.cz
    © 1999-2015 Nitemedia s. r. o. Všechna práva vyhrazena.