Código Natural/Notação posicional: mudanças entre as edições

m
 
(17 revisões intermediárias pelo mesmo usuário não estão sendo mostradas)
Linha 3: Linha 3:
[[Cadeia de bits|Cadeias de bits]] são a forma mais simples para se registrar números ou códigos naturais, mas para o ser humano elas são muito longas e difíceis de ler. No caso dos números existe a  [[wikipedia:Positional notation|notação posicional em base ''N'']], mais compacta que a representação binária para qualquer ''N''>2.  
[[Cadeia de bits|Cadeias de bits]] são a forma mais simples para se registrar números ou códigos naturais, mas para o ser humano elas são muito longas e difíceis de ler. No caso dos números existe a  [[wikipedia:Positional notation|notação posicional em base ''N'']], mais compacta que a representação binária para qualquer ''N''>2.  


A notação numérica pode ser facilmente adaptada para expressar códigos naturais. Exemplos:
A notação numérica pode ser facilmente adaptada para expressar códigos naturais, basta permitir zeros a esquerda. Exemplos:


{| class="wikitable"
{| class="wikitable"
Linha 9: Linha 9:
|'''Código'''
|'''Código'''
|'''''Número'''''
|'''''Número'''''
|
|'''Código'''
|'''Código'''
|'''''Número'''''
|'''''Número'''''
|-
|-
|[[wikipedia:Binary number|Base 2. Binária]] / Ilegível ||<code>00010010</code>||''10010''  || <code>1111</code> || ''1111''
|[[wikipedia:Binary number|Base 2. Binária]] / Ilegível ||<code>000000010010</code>||''10010''  || ||<code>1111</code> || ''1111''
|-
|-
|[[wikipedia:Quaternary numeral system|Base 4. Quaternaria]] / Melhorou! ||<code>0102</code>||''102'' || <code>33</code> || ''33''
|[[wikipedia:Quaternary numeral system|Base 4. Quaternaria]] / Melhorou! ||<code>000102</code>||''102'' || ||<code>33</code> || ''33''
|-
|-
|[[wikipedia:Hexadecimal|Base 16. Hexadecimal]] / Mais compacta ||<code>12</code>||''12'' || <code>f</code> || ''f''
|[[wikipedia:Hexadecimal|Base 16. Hexadecimal]] / Compacta ||<code>012</code>||''12'' || ||<code>f</code> || ''f''
|}
|}


Alguns cuidados devem ser tomados, como o tratamento dos zeros a esquerda, importante diferenciador de códigos. Notar o exemplo {{baseNh|00010010|2}} que manteve seu zero a esquerda em {{baseNh|0102|4}}. E existem ainda códigos que não podem ser representados em certas bases. Por exemplo o código {{baseNh|010|2}} não pode ser representado na base 4. Se representar como {{baseNh|02|4}}  vai ser confundido com o binário {{baseNh|0010|2}}. Outros exemplos:
Notar o exemplo do código {{baseNh|000000010010|2}} que manteve seus zeros a esquerda na sua representação quaternária,  {{baseNh|000102|4}}. Os zeros a esquerda são importantes diferenciadores dos códigos, todavia existem restrições. Existem códigos binários que não podem ser representados nas bases numéricas usuais. Exemplos:


:{| class="wikitable"
:{| class="wikitable"
|'''Base2''' || <code>0</code> || <code>00</code> || <code>0000</code> || <code>010</code> || <code>1010</code> || <code>10100</code>
|'''Base2''' || '''<code>0</code>''' <br/><small>(1 dígito)</small>|| '''<code>00</code>''' <br/><small>(2 dígitos)</small> || '''<code>0000</code>'''  <br/><small>(4 dígitos)</small>|| '''<code>010</code>''' <br/><small>(3 dígitos)</small> || '''<code>1010</code>'''  <br/><small>(4 dígitos)</small> || '''<code>10100</code>''' <br/><small>(5 dígitos)</small> || '''<code>010100</code>''' <br/><small>(6 dígitos)</small> || '''<code>00010100</code>''' <br/><small>(8 dígitos)</small>
|-
|-
|'''Base4''' || ? || <code>0</code> || <code>00</code> || ? || <code>22</code> || ?
|'''Base4''' || <code style="color:red;font-size: x-large; font-weight:bold">?</code> || <code>0</code> || <code>00</code> || <code style="color:red;font-size: x-large; font-weight:bold">?</code> || <code>22</code> || <code style="color:red;font-size: x-large; font-weight:bold">?</code> || <code>110</code>|| <code>0110</code>
|-
|-
|'''Base16''' || ? || ? || <code>0</code> || ? || <code>a</code> || ?
|'''Base16''' || <code style="color:red;font-size: x-large; font-weight:bold">?</code> || <code style="color:red;font-size: x-large; font-weight:bold">?</code> || <code>0</code> || <code style="color:red;font-size: x-large; font-weight:bold">?</code> || <code>a</code> || <code style="color:red;font-size: x-large; font-weight:bold">?</code> || <code style="color:red;font-size: x-large; font-weight:bold">?</code> || <code>14</code>
|}
|}
O código {{baseNh|010|2}} não pode ser representado na base 4 pois se permitíssimos algo como "{{baseNh|02|4}}"  seria confundido com o binário {{baseNh|0010|2}}. Assim nas demais interrogações da ''base 4'', apenas os binários com uma quantidade par de dígitos (2, 4 e 6) podem ser representados. As interrogações da ''base 16'' surgem quando a quantidade de dígitos binários não é divisível por quatro &mdash; temos interrogações em 1, 2,  3, 5 ou  6 dígitos binários. 


== Definição ==
== Definição ==
Linha 163: Linha 166:


==== Base 32 ====
==== Base 32 ====
Ver [[wikipedia:Base 32]]. Para aplicações que requerem maior grau de compactação, a base 32 é a potência de 2 que se encontra entre os dois limites:
Ver [[wikipedia:Base 32]] e [[#Base_N|acima em Base N]] as variantes (''base32hex'', ''base32ghs'', etc.). Para aplicações que requerem maior grau de compactação, a ''base 32'' é a potência de 2 que se encontra ainda abaixo do limite  superior. São dois limites, conforme o tipo de aplicação:
* base36 é o limite alfanumérico resiliente, onde não há confusão entre maiúsculas e minúsculas.
 
* base 64 é o limite alfanumérico (10 + 26*2 + 2 caracteres ASCII usuais).
* ''base 36'' é o limite alfanumérico resiliente, onde não há confusão entre maiúsculas e minúsculas.<br/>É o limite adotado em aplicações que envolvem interpretação ou comunicação humanas, tais como voz, chat, URLs curtas, aplicações cartoriais, placas, etc. Algumas tecnologias, como QR-Codes também se beneficiam do case-insensitive.  Como 36 não é potência de 2 (portanto não é interoperável), o 32 é preferido como máximo.
 
* ''base 64'' é o limite alfanumérico (10 + 26*2 + 2 caracteres ASCII usuais).<br/>É o limite para aplicações onde é permitida a diferenciação maiúsculas/minúsculas. A bsase32 seria preferível à base64 em códigos de poucos bits, onde o ganho de compactação seja notado, e a oferta de hierarquia tenha um papel importante.
 
Até o momento foram aceitas apenas 4 "variantes padronizadas", conforme [[#Base N|tabela acima]]: ''base32hex'', ''base32ghs'', ''base32nvu'' e ''base32rfc''.


=== Base Nh ===
=== Base Nh ===
Linha 363: Linha 370:


=== Encode e decode Nh ===
=== Encode e decode Nh ===
A seguir o algoritmos completos, expresso através de [[wikipedia:PL/pgSQL|linguagem PLpgSQL]]. Do inglês "''encode''" codifica em base Nh, e "''decode''" decodifica a base Nh.
A seguir os algoritmos completos, expressos como funções [[wikipedia:PL/pgSQL|linguagem PLpgSQL]]"''encode''" codifica em base Nh, e "''decode''" decodifica a base Nh.
 
No [[wikipedia:SQL:1992|padrão SQL:1992]] a representação interna em [[cadeia de bits]] foi denominada ''BIT VARYING'', sendo [[wikipedia:SQL:2003|descontinuada em 2003]]. No PostgreSQL, todavia, [https://www.postgresql.org/docs/current/datatype-bit.html o tipo de dado] e seus [https://www.postgresql.org/docs/current/functions-bitstring.html operadores e funções] foram mantidos, sendo abreviado como ''varbit'' &mdash; e nos nomes de função da biblioteca NatCod abreviada como ''vbit''.
 
O "encode" é a conversão "vbit to base-h", o "decode" é a conversão "base-h to vbit". Daí os nomes de função <code>vbit_to_baseh()</code> e  <code>baseh_to_vbit()</code>, com implementação completa no [https://git.osm.codes/NaturalCodes/tree/main/src-sql SQL-schema NatCode]. A seguir os algoritmos simplificados.  


Função geral de "encode bitstring" para uma base Nh. Converte uma cadeia de bits em texto base2h, base4h, base8h ou base16h.
Função simplificada de "encode bitstring", converte uma cadeia de bits em texto base-h.
<syntaxhighlight lang="sql">
<syntaxhighlight lang="sql">
CREATE FUNCTION natcod.vbit_to_baseh(
CREATE FUNCTION natcod.vbit_to_baseh(
   p_val varbit,  -- input
   p_val varbit,  -- input
   p_base int DEFAULT 4, -- selecting base2h, base4h, base8h, or base16h.
   p_base int DEFAULT 16 -- 16 for base16h (default), 8 for base8h, 4 for base4h or 2 for base2h.
  p_nhDigits_upper boolean default false  -- represent non-hierarchical digits in upper case
) RETURNS text AS $f$
) RETURNS text AS $f$
DECLARE
DECLARE
Linha 378: Linha 387:
     ret text := '';
     ret text := '';
     blk varbit;
     blk varbit;
    blk_n int;
     bits_per_digit int;
     bits_per_digit int;
     tr int[] := '{ {1,2,0,0}, {1,3,4,0}, {1,3,5,6} }'::int[]; -- --4h(bits,pos), 8h(bits,pos)
     tr int[] := '{ {1,2,0,0}, {1,3,4,0}, {1,3,5,6} }'::int[]; -- --4h(bits,pos), 8h(bits,pos)
     tr_selected JSONb;
     tr_selected JSONb;
     trtypes JSONb := '{"2":[1,1], "4":[1,2], "8":[2,3], "16":[3,4]}'::JSONb; -- TrPos,bits. Can optimize? by sparse array.
     trtypes JSONb := '{"2":[1,1], "4":[1,2], "8":[2,3], "16":[3,4]}'::JSONb;
     trpos int;
     trpos int;
     baseh "char"[] := array[ -- new 2023 standard for Baseh:
     baseh "char"[] := array[ -- the standards for Baseh:
      '[0:15]={g,q,x,x,x,x,x,x,x,x,x,x,x,x,x,x}'::"char"[], --1. 1 bit in 4h,8h,16h
      '[0:15]={0,1,2,3,x,x,x,x,x,x,x,x,x,x,x,x}'::"char"[], --2. 2 bits in 4h
      '[0:15]={h,m,r,v,x,x,x,x,x,x,x,x,x,x,x,x}'::"char"[], --3. 2 bits 8h,16h
      '[0:15]={0,1,2,3,4,5,6,7,x,x,x,x,x,x,x,x}'::"char"[], --4. 3 bits in 8h
      '[0:15]={j,k,n,p,s,t,z,y,x,x,x,x,x,x,x,x}'::"char"[], --5. 3 bits in 16h
      '[0:15]={0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f}'::"char"[]  --6. 4 bits in 16h
    ]; -- jumpping I,O and L,U,W,X letters!
      -- the standard alphabet is https://tools.ietf.org/html/rfc4648#section-6
BEGIN
  IF (p_nhDigits_upper) THEN
    baseh := array[
       '[0:15]={G,Q,x,x,x,x,x,x,x,x,x,x,x,x,x,x}'::"char"[], --1. 1 bit in 4h,8h,16h
       '[0:15]={G,Q,x,x,x,x,x,x,x,x,x,x,x,x,x,x}'::"char"[], --1. 1 bit in 4h,8h,16h
       '[0:15]={0,1,2,3,x,x,x,x,x,x,x,x,x,x,x,x}'::"char"[], --2. 2 bits in 4h
       '[0:15]={0,1,2,3,x,x,x,x,x,x,x,x,x,x,x,x}'::"char"[], --2. 2 bits in 4h
Linha 402: Linha 399:
       '[0:15]={J,K,N,P,S,T,Z,Y,x,x,x,x,x,x,x,x}'::"char"[], --5. 3 bits in 16h
       '[0:15]={J,K,N,P,S,T,Z,Y,x,x,x,x,x,x,x,x}'::"char"[], --5. 3 bits in 16h
       '[0:15]={0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f}'::"char"[]  --6. 4 bits in 16h
       '[0:15]={0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f}'::"char"[]  --6. 4 bits in 16h
     ];
      -- Hexadecimals by standard alphabet of https://tools.ietf.org/html/rfc4648#section-6
  END IF;
     ]; -- jumpping I,O and L,U,W,X letters.
BEGIN
   vlen := bit_length(p_val);
   vlen := bit_length(p_val);
   tr_selected := trtypes->(p_base::text);  -- can be array instead of JSON
   tr_selected := trtypes->(p_base::text);
  IF p_val IS NULL OR tr_selected IS NULL OR vlen=0 THEN
    RETURN NULL; -- or  p_retnull;
  END IF;
   IF p_base=2 THEN
   IF p_base=2 THEN
     RETURN $1::text; --- direct bit string as string
     RETURN $1::text; -- bit string as string
   END IF;
   END IF;
   bits_per_digit := (tr_selected->>1)::int;
   bits_per_digit := (tr_selected->>1)::int;
  blk_n := vlen/bits_per_digit;
   pos0  := (tr_selected->>0)::int;
   pos0  := (tr_selected->>0)::int;
   trpos := tr[pos0][bits_per_digit];
   trpos := tr[pos0][bits_per_digit];
   FOR counter IN 1..blk_n LOOP
   FOR counter IN 1..(vlen/bits_per_digit) LOOP
       blk := substring(p_val FROM 1 FOR bits_per_digit);
       blk := substring(p_val FROM 1 FOR bits_per_digit);
       ret := ret || baseh[trpos][ varbit_to_int(blk,bits_per_digit) ];
       ret := ret || baseh[trpos][ varbit_to_int(blk,bits_per_digit) ];
       p_val := substring(p_val FROM bits_per_digit+1); -- same as p_val<<(bits_per_digit*blk_n)
       p_val := substring(p_val FROM bits_per_digit+1);
   END LOOP;
   END LOOP;
   vlen := bit_length(p_val);
   vlen := bit_length(p_val);
   IF p_val!=b'' THEN -- vlen % bits_per_digit>0
   IF p_val!=b'' THEN
     trpos := tr[pos0][vlen];
     trpos := tr[pos0][vlen];
     ret := ret || baseh[trpos][ varbit_to_int(p_val,vlen) ];
     ret := ret || baseh[trpos][ varbit_to_int(p_val,vlen) ];
Linha 428: Linha 422:
   RETURN ret;
   RETURN ret;
END
END
$f$ LANGUAGE plpgsql IMMUTABLE;
$f$ LANGUAGE PLpgSQL IMMUTABLE;
</syntaxhighlight>
</syntaxhighlight>


Função geral de "decode bitstring" para uma base Nh. Converte o texto base Nh para sua representação interna ''bitstring''.
Função geral de "decode base Nh". Converte o texto base-h para sua representação interna ''bitstring''.


<syntaxhighlight lang="sql">
<syntaxhighlight lang="sql">
CREATE FUNCTION natcod.baseh_to_vbit(
CREATE FUNCTION natcod.baseh_to_vbit(
   p_val text,  -- input (enforced lower case)
   p_val text,  -- input (enforced lower case)
   p_base int DEFAULT 4 -- selecting base2h, base4h, base8h, or base16h.
   p_base int DEFAULT 16 -- selecting base2h, base4h, base8h, or base16h.
) RETURNS varbit AS $f$
) RETURNS varbit AS $f$
DECLARE
DECLARE
   tr_hdig jsonb := '{
   tr_hdig jsonb := '{
     "g":[1,0],"q":[1,1],
     "G":[1,0],"Q":[1,1],
     "h":[2,0],"m":[2,1],"r":[2,2],"v":[2,3],
     "H":[2,0],"M":[2,1],"R":[2,2],"V":[2,3],
     "j":[3,0],"k":[3,1],"n":[3,2],"p":[3,3],
     "J":[3,0],"K":[3,1],"N":[3,2],"P":[3,3],
     "s":[3,4],"t":[3,5],"z":[3,6],"y":[3,7]
     "S":[3,4],"T":[3,5],"Z":[3,6],"Y":[3,7]
   }'::jsonb;
   }'::jsonb;
   tr_full jsonb := '{
   tr_full jsonb := '{
Linha 456: Linha 450:
   BEGIN
   BEGIN
   ret = '';
   ret = '';
   blk := regexp_match(p_val,'^([0-9a-f]*)([ghjkmnp-tvzy])?$');
   blk := regexp_match(p_val,'^([0-9a-f]*)([GHJKMNP-TVZY])?$');
   IF blk[1] >'' THEN
   IF blk[1] >'' THEN
     FOREACH i IN ARRAY regexp_split_to_array(blk[1],'') LOOP
     FOREACH i IN ARRAY regexp_split_to_array(blk[1],'') LOOP
Linha 487: Linha 481:
Na ''Base 16h'' portanto apresenta rótulos para todos os níveis, do L0 ao L4 e seus intermediários: ''L0'',&nbsp;''L0.5'', ''L1'', ''L1.5'', ''L2'', ''L2.5'', ''L3, L3.5'',&nbsp;''L4.''  Resulta em um sistema com 5×2-1=9 grades hierárquicas, conforme a ilustração acima. Para qualquer que seja o nível máximo ''LM'' (no exemplo ''L4'' portanto ''M''=4), a Base&nbsp;16h resultará em um '''sistema completo de grades''', com ''(M+1)''×2-1 níveis.
Na ''Base 16h'' portanto apresenta rótulos para todos os níveis, do L0 ao L4 e seus intermediários: ''L0'',&nbsp;''L0.5'', ''L1'', ''L1.5'', ''L2'', ''L2.5'', ''L3, L3.5'',&nbsp;''L4.''  Resulta em um sistema com 5×2-1=9 grades hierárquicas, conforme a ilustração acima. Para qualquer que seja o nível máximo ''LM'' (no exemplo ''L4'' portanto ''M''=4), a Base&nbsp;16h resultará em um '''sistema completo de grades''', com ''(M+1)''×2-1 níveis.


Abaixo células ''L0'' de cobertura base16 do Brasil, ilustrando caso concreto de grades de diferentes níveis. Elas foram rotuladas pela Curva-Z espelhada verticalmente.
Abaixo células ''L0'' de cobertura base16 do Brasil, ilustrando caso concreto de grades de diferentes níveis. Elas foram rotuladas pela Curva-Z espelhada verticalmente &mdash; a orientação adotada nos eixos resulta em variantes da curva (N e И) e da sua ordenação.


[[Arquivo:XY-FlippedVertically.png|centro|semmoldura|420px]]
[[Arquivo:XY-FlippedVertically.png|centro|semmoldura|480px]]


[[Arquivo:BR-SciCode-Base16h.png|centro|720x720px]]
[[Arquivo:BR-SciCode-Base16h.png|centro|720x720px]]
2 391

edições