Systemy pozycyjne o podstawie większej od 10


Podrozdziały   Tematy pokrewne

 

Cyfry w systemie pozycyjnym o p > 10

W systemach o podstawie p większej od 10 obowiązują wszystkie podane przez nas wzory i algorytmy. Jedyną różnicą są cyfry, których musi być dokładnie tyle ile wynosi podstawa p. Niestety, cyfr "wymyślono" tylko 10. Brakujące cyfry zastępujemy kolejnymi literkami alfabetu, I tak:

 

litera A (lub a) odpowiada cyfrze o wartości 10
litera B (lub b) odpowiada cyfrze o wartości 11
litera C (lub c) odpowiada cyfrze o wartości 12
...

 

Sposób ten pozwala nam zapisywać liczby w systemach pozycyjnych o podstawie od 2 do 36. Dla większych podstaw musimy wymyślić inną formę przedstawiania cyfr, ponieważ braknie nam literek. Na szczęście są to problemy czysto teoretyczne, ponieważ w informatyce będziemy się spotykać tylko z systemem dwójkowym, ósemkowym, dziesiętnym oraz szesnastkowym. Inne systemy stosowane są marginalnie.

 

Przykład:

Oblicz wartość liczby pozycyjnej ABCD,EF(16).

 

ABCD,EF(16) = A • 163 + B • 162 + C • 161 + D • 160 + E • 16-1 + F • 16-2

 

Zastępujemy znaki cyfr ich wartościami liczbowymi:

 

ABCD,EF(16) = 10 × 163 + 11 × 162 + 12 × 161 + 13 × 160 + 14 × 16-1 + 15 × 16-2
ABCD,EF(16) = 10 × 4096 + 11 × 256 + 12 × 16 + 13 × 1 + 14 × 1/16 + 15 × 1/256
ABCD,EF(16) = 40960 + 2816 + 192 + 13 + 14/16 + 15/256
ABCD,EF(16) = 43981 + 224/256 + 15/256
ABCD,EF(16) = 43981 + 239/256 = 43981,93359375(10).

 

Przelicz liczbę dziesiętną 2427,423 na system piętnastkowy z dokładnością do 6 cyfr po przecinku.

W systemie piętnastkowym mamy piętnaście cyfr {0,1,2,3,4,5,6,7,8,9,A,B,C,D,E}.

Rozdzielamy liczbę na część całkowitą i ułamkową i wyznaczamy wartości kolejnych cyfr, które następnie zastępujemy odpowiadającymi tym wartością znakami cyfr.

 

2427 div 15 =  161  i reszta 12  - cyfra C
161 div 15 = 10  i reszta 11  - cyfra B
10 div 15 = 0  i reszta 10  - cyfra A

 

2427(10) = ABC(15)

 

0,423 • 15 =  6,345  - cyfra 6
0,345 • 15 = 5,175  - cyfra 5
0,175 • 15 = 2,625  - cyfra 2
0,625 • 15 = 9,375  - cyfra 9
0,375 • 15 = 5,625  - cyfra 5
0,625 • 15 = 9,375  - cyfra 9

 

0,423(10) = 0,652959...(15).


Ponieważ w części ułamkowej nie otrzymaliśmy zera, wyznaczona liczba ma wartość przybliżoną.

Składamy obie wyznaczone części liczby w jedną całość i otrzymujemy wynik:

 

2427,423(10) = ABC,652959...(15).

 

Aby poprawnie przeliczać liczby w systemach o p > 10, podamy dwa proste algorytmy, które kojarzą znak cyfry w postaci ASCII z jej wartością. Algorytmy te wykorzystujemy w programach przy przekształcaniu wartości cyfry na odpowiadający jej znak ASCII oraz przy wyliczaniu wartości cyfry na podstawie jej znaku ASCII.

 

Obliczanie wartości cyfry ze znaku ASCII
  1. Zamień znak na dużą literę.
  2. Od kodu znaku odejmij 48.
  3. Jeśli otrzymałeś wartość większą od 9, to odejmij jeszcze 7.

 
Obliczanie znaku ASCII reprezentującego daną cyfrę
  1. Jeśli cyfra ma wartość mniejszą od 10, to kod znaku otrzymasz dodając do wartości cyfry liczbę 48.
  2. W przeciwnym razie kod znaku otrzymamy dodając do wartości cyfry liczbę 55.

 


DLA
GENIUSZA

Programy

Program przelicza liczby z jednego systemu pozycyjnego (podstawa od 2 do 36) na inny (podstawa od 2 do 36), wykorzystując podane algorytmy. W obliczeniach na dalszych miejscach po przecinku mogą pojawić się błędy spowodowane zaokrąglaniem wartości zmiennoprzecinkowych.

 

Efekt uruchomienia programu
Przelicznik liczb zapisanych w różnych
       systemach pozycyjnych
--------------------------------------
(C)2005 mgr Jerzy Wałaszek I LO Tarnów

Podaj liczbę wejściową   = 22,1

Podaj podstawę wejściową = 3

Podaj podstawę docelową  = 5

22,1(3) = 13,131313131313131313131(5)

Koniec pracy z programem ? (T = TAK)

 

Borland
Delphi 7.0
Personal
Edition
// Program przeliczający liczby z jednego
// systemu pozycyjnego na inny.
//---------------------------------------
// (C)2005 mgr Jerzy Wałaszek
// I Liceum Ogólnokształcące
// im. K. Brodzińskiego
// w Tarnowie
//---------------------------------------

program Systemy;

{$APPTYPE CONSOLE}

// Funkcja zadaje użytkownikowi pytanie, czy chce
// zakończyć pracę z programem. Jeśli tak, zwraca
// wartość logiczną true.
//-----------------------------------------------
function Koniec : boolean;
var
  s : string;
begin
  write('Koniec pracy z programem ? (T = TAK)');
  readln(s);
  Koniec := (s <> '') and (UpCase(s[1]) = 'T');
end;

// Funkcja sprawdza, czy użytkownik wprowadził
// poprawne dane wejściowe. W takim przypadku
// zwraca wartość true, inaczej zwraca false.
//--------------------------------------------
function DaneOK(var s : string; p1,p2 : cardinal) : boolean;
var
  przecinek : boolean;
  i,c       : cardinal;
begin
  DaneOK := true;
  if (p1 < 2) or (p1 > 36) or (p2 < 2) or (p2 > 36) then
    DaneOK := false;
  while (s <> '') and (s[1] = ' ') do Delete(s,1,1);
  przecinek := false;
  for i := 1 to length(s) do
    case UpCase(s[i]) of
      ',' : if przecinek then
            begin
              DaneOK := false; break;
            end
            else przecinek := true;
      '0'..'9',
      'A'..'Z': begin
                  c := ord(UpCase(s[i])) - 48;
                  if c > 9 then dec(c,7);
                  if c >= p1 then
                  begin
                    DaneOK := false; break;
                  end;
                end;
      else
      begin
        DaneOK := false; break;
      end;
    end;
end;

// **********************
// *** PROGRAM GŁÓWNY ***
// **********************

var
  s1,s2             : string;
  c,i,p1,p2,Lc,Lu,w : cardinal;
  u                 : boolean;
  rLu               : real;

begin
  writeln('Przelicznik liczb zapisanych w roznych');
  writeln('       systemach pozycyjnych');
  writeln('--------------------------------------');
  writeln('(C)2005 mgr Jerzy Walaszek I LO Tarnow');
  repeat
    writeln;
    write('Podaj liczbe wejsciowa   = '); readln(s1);
    writeln;
    write('Podaj podstawe wejsciowa = '); readln(p1);
    writeln;
    write('Podaj podstawe docelowa  = '); readln(p2);
    writeln;
    if DaneOK(s1,p1,p2) then
    begin
      Lc := 0; Lu := 0; w := 1; u := false;
      for i := 1 to length(s1) do
        if s1[i] = ',' then
          u := true
        else
        begin
          c := ord(UpCase(s1[i])) - 48;
          if c > 9 then dec(c,7);
          if u then
          begin
            Lu := p1 * Lu + c;
            w := p1 * w;
          end
          else
            Lc := p1 * Lc + c;
        end;
      rLu := Lu / w;
      s2 := '';
      repeat
        c  := Lc mod p2;
        if c < 10 then
          s2 := char(c + 48) + s2
        else
          s2 := char(c + 55) + s2;
        Lc := Lc div p2;
      until Lc = 0;
      if Lu > 0 then
      begin
        s2 := s2 + ',';
        w := Round(15 * ln(10) / ln(p2)); // ograniczamy cyfry po przecinku 
        while (w > 0) and (length(s2) < 32) do
        begin
          dec(w);
          rLu := rLu * p2;
          c  := trunc(rLu);
          if c < 10 then
            s2 := s2 + char(c + 48)
          else
            s2 := s2 + char(c + 55);
          rLu := rLu - c;
        end;
        while s2[length(s2)] = '0' do Delete(s2,length(s2),1);
      end;
      writeln(s1,'(',p1,') = ',s2,'(',p2,')');
    end
    else
      writeln('Zle dane. Obliczenia przerwane.');
    writeln;
  until Koniec;
end.
Borland
C++ Builder
6.0
Personal
Edition
// Program przeliczający liczby z jednego
// systemu pozycyjnego na inny.
//---------------------------------------
// (C)2005 mgr Jerzy Wałaszek
// I Liceum Ogólnokształcące
// im. K. Brodzińskiego
// w Tarnowie
//---------------------------------------

#include <cmath>
#include <iostream>
#include <string>

using namespace std;

// Funkcja zadaje użytkownikowi pytanie, czy chce
// zakończyć pracę z programem. Jeśli tak, zwraca
// wartość logiczną true.
//-----------------------------------------------
bool Koniec()
{
  string s;

  cout << "Koniec pracy z programem ? (T = TAK)";
  cin >> s;
  return ((s != "") && (toupper(s[0]) == 'T'));
}

// Funkcja sprawdza, czy użytkownik wprowadził
// poprawne dane wejściowe. W takim przypadku
// zwraca wartość true, inaczej zwraca false.
//--------------------------------------------
bool DaneOK(string & s, unsigned p1, unsigned p2)
{
  bool przecinek;
  unsigned long i,c;

  if((p1 < 2) || (p1 > 36) || (p2 < 2) || (p2 > 36)) return false;
  przecinek = false;
  for(i = 0; i < s.length(); i++)
  {
    s[i] = toupper(s[i]);
    if(s[i] == ',')
    {
      if(przecinek)
        return false;
      else
      {
        przecinek = true; continue;
      };
    };
    if((s[i] < '0') || (s[i] > 'Z') || ((s[i] > '9') && (s[i] < 'A')))
      return false;
    c = s[i] - 48;
    if(c > 9) c -= 7;
    if(c >= p1) return false;
  }
  return true;
}

// **********************
// *** PROGRAM GŁÓWNY ***
// **********************

main()
{
  string s1,s2;
  unsigned c,i,p1,p2,Lc,Lu,w;
  bool u;
  double rLu;
  char z[1];

  cout << "Przelicznik liczb zapisanych w roznych\n"
          "       systemach pozycyjnych\n"
          "--------------------------------------\n"
          "(C)2005 mgr Jerzy Walaszek I LO Tarnow\n";
  do
  {
    cout << "\nPodaj liczbe wejsciowa   = "; cin >> s1;
    cout << "\nPodaj podstawe wejsciowa = "; cin >> p1;
    cout << "\nPodaj podstawe docelowa  = "; cin >> p2;
    cout << endl;
    if(DaneOK(s1,p1,p2))
    {
      Lc = Lu = 0; w = 1; u = false;
      for(i = 0; i < s1.length(); i++)
        if(s1[i] == ',')
          u = true;
        else
        {
          c = s1[i] - 48;
          if(c > 9) c -= 7;
          if(u)
          {
            Lu = p1 * Lu + c; w  *= p1;
          }
          else Lc = p1 * Lc + c;
        }
      rLu = (double)(Lu) / w; s2 = "";
      do
      {
        c  = Lc % p2;
        if(c < 10)
          s2 = (char)(c + 48) + s2;
        else
          s2 = (char)(c + 55) + s2;
        Lc /= p2;
      } while(Lc);
      if(Lu)
      {
        s2 += ',';
        w = (15 * logl(10) / logl(p2)); // ograniczamy cyfry po przecinku 
        while((w > 0) && (s2.length() < 32))
        {
          w--;
          rLu *= p2;
          c    = (unsigned)floor(rLu);
          if(c < 10)
            s2 += (char)(c + 48);
          else
            s2 += (char)(c + 55);
          rLu = rLu - c;
        }
        while(s2[s2.length()-1] == '0') s2.erase(s2.length()-1);
      }
      cout << s1 << "(" << p1 << ") = " << s2 << "(" << p2 << ")\n";
    }    
    else cout << "Zle dane. Obliczenia przerwane.\n";
    cout << endl;
  } while(!Koniec());
}
Microsoft
Visual
Basic 2005
Express
Edition
' Program przeliczający liczby z jednego
' systemu pozycyjnego na inny.
'---------------------------------------
' (C)2005 mgr Jerzy Wałaszek
' I Liceum Ogólnokształcące
' im. K. Brodzińskiego
' w Tarnowie
'---------------------------------------

Option Explicit On

Module Module1

  ' Funkcja zadaje użytkownikowi pytanie, czy chce
  ' zakończyć pracę z programem. Jeśli tak, zwraca
  ' wartość logiczną true.
  '-----------------------------------------------
  Function Koniec() As Boolean
    Dim s As String

    Console.WriteLine("Koniec pracy z programem ? (T = TAK) ")
    s = Console.ReadLine.ToUpper()
    Return (s = "T")
  End Function

  ' Funkcja sprawdza, czy użytkownik wprowadził
  ' poprawne dane wejściowe. W takim przypadku
  ' zwraca wartość true, inaczej zwraca false.
  '--------------------------------------------
  Function DaneOK(ByVal s As String, ByVal p1 As UInteger, _
                  ByVal p2 As UInteger) As Boolean
    Dim przecinek As Boolean
    Dim i, c As UInteger
    Dim x As Char
    
    If (p1 < 2) Or (p1 > 36) Or (p2 < 2) Or (p2 > 36) Then
      Return False
    End If
    s = s.TrimStart(" ")
    przecinek = False
    For i = 0 To s.Length() - 1
      x = s.Chars(i)
      If x = "," Then
        If przecinek Then
          Return False
        Else
          przecinek = True
        End If
      ElseIf ((x >= "0") And (x <= "9")) Or _
             ((x >= "A") And (x <= "Z")) Then
        c = Asc(x) - 48
        If c > 9 Then c = c - 7
        If c >= p1 Then Return False
      Else : Return False
      End If
    Next
    Return True
  End Function

  Sub Main()

    Dim s1, s2 As String
    Dim c, i, p1, p2, Lc, Lu, w As UInteger
    Dim u As Boolean, rLu As Double

    Console.WriteLine("Przelicznik liczb zapisanych w różnych")
    Console.WriteLine("       systemach pozycyjnych")
    Console.WriteLine("--------------------------------------")
    Console.WriteLine("(C)2005 mgr Jerzy Wałaszek I LO Tarnów")
    Do
      Console.WriteLine()
      Console.Write("Podaj liczbę wejściową   = ")
      s1 = Console.ReadLine.ToUpper()
      Console.WriteLine()
      Console.Write("Podaj podstawę wejściową = ")
      p1 = Val(Console.ReadLine)
      Console.WriteLine()
      Console.Write("Podaj podstawę docelową  = ")
      p2 = Val(Console.ReadLine)
      Console.WriteLine()
      If DaneOK(s1, p1, p2) Then
        Lc = 0 : Lu = 0 : w = 1 : u = False
        For i = 0 To s1.Length() - 1
          If s1.Chars(i) = "," Then
            u = True
          Else
            c = Asc(s1.Chars(i)) - 48
            If c > 9 Then c = c - 7
            If u Then
              Lu = p1 * Lu + c : w *= p1
            Else
              Lc = p1 * Lc + c
            End If
          End If
        Next
        rLu = Lu / w : s2 = ""
        Do
          c = Lc Mod p2
          If c < 10 Then
            s2 = Chr(c + 48) + s2
          Else
            s2 = Chr(c + 55) + s2
          End If
          Lc \= p2
        Loop Until Lc = 0
        If Lu > 0 Then
          s2 += ","
          w = Int(15 * Math.Log(10) / Math.Log(p2))
          While (w > 0) And (s2.Length() < 32)
            w -= 1
            rLu *= p2
            c = Int(rLu)
            If c < 10 Then
              s2 += Chr(c + 48)
            Else
              s2 += Chr(c + 55)
            End If
            rLu -= c
          End While
          s2 = s2.TrimEnd("0")
        End If
        Console.WriteLine("{0}({1}) = {2}({3})", s1, p1, s2, p2)
      Else
        Console.WriteLine("Złe dane. Obliczenia przerwane.")
      End If
      Console.WriteLine()
    Loop Until Koniec()

  End Sub

End Module
JavaScript
<html>
  <head>
  </head>
  <body>
    <div align="center">
<form style="BORDER-RIGHT: #ff9933 1px outset;
             PADDING-RIGHT: 4px;
             BORDER-TOP: #ff9933 1px outset;
             PADDING-LEFT: 4px;
             PADDING-BOTTOM: 1px;
             BORDER-LEFT: #ff9933 1px outset;
             PADDING-TOP: 1px;
             BORDER-BOTTOM: #ff9933 1px outset;
             BACKGROUND-COLOR: #ffcc66"
      name="frmprzelicz">
  <h3 id="data_out" style="text-align: center">
    Przeliczanie liczb zapisanych<br>
    w różnych systemach pozycyjnych
  </h3>
  <p style="TEXT-ALIGN: center">
    (C)2005 mgr Jerzy Wałaszek&nbsp;&nbsp; I LO w Tarnowie
  </p>
  <hr>
  <div align="center">
    <table border="0" cellpadding="4" style="border-collapse: collapse">
      <tr>
        <td align="right">Liczba wejściowa =</td>
        <td>
<input value="12,75" name="inp_s1" size="20" style="text-align: right">
        </td>
        <td align="right">Podstawa wejściowa =&nbsp;</td>
        <td>
<input value="10" name="inp_p1" size="20" style="text-align: right">
        </td>
      </tr>
      <tr>
        <td align="center" colspan="2">
          <input onclick="main();"
                 type="button"
                 value="Wyznacz liczbę docelową"
                 name="B1">
        </td>
        <td align="right">Podstawa docelowa =&nbsp;</td>
        <td>
<input value="2" name="inp_p2" size="20" style="text-align: right">
        </td>
      </tr>
    </table>
  </div>
  <p style="TEXT-ALIGN: center" id="out_t">...</p>
</form>

<script language=javascript>

// Program przeliczający liczby z jednego
// systemu pozycyjnego na inny.
//---------------------------------------
// (C)2005 mgr Jerzy Wałaszek
// I Liceum Ogólnokształcące
// im. K. Brodzińskiego
// w Tarnowie
//---------------------------------------

// Funkcja sprawdza, czy użytkownik wprowadził
// poprawne dane wejściowe. W takim przypadku
// zwraca wartość true, inaczej zwraca false.
//--------------------------------------------
function DaneOK(s,p1,p2)
{
  var przecinek,i,c;

  if((p1 < 2) || (p1 > 36) || (p2 < 2) || (p2 > 36)) return false;
  przecinek = false;
  for(i = 0; i < s.length; i++)
  {
    if(s.charAt(i) == ',')
    {
      if(przecinek) return false;
      else
      {
        przecinek = true; continue;
      }
    }
    if((s.charAt(i) < '0') || (s.charAt(i) > 'Z') ||
      ((s.charAt(i) > '9') && (s.charAt(i) < 'A'))) return false;
    c = s.charCodeAt(i) - 48;
    if(c > 9) c -= 7;
    if(c >= p1) return false;
  }
  return true;
}

// **********************
// *** PROGRAM GŁÓWNY ***
// **********************

function main()
{
  var s1,c,i,p1,p2,Lc,Lu,w,u,rLu,t;

  s1 = document.frmprzelicz.inp_s1.value;
  s1 = s1.toUpperCase();
  p1 = parseInt(document.frmprzelicz.inp_p1.value);
  p2 = parseInt(document.frmprzelicz.inp_p2.value);
  if(isNaN(p1) || isNaN(p2) || !DaneOK(s1,p1,p2))
    t = "<font color=Red><b>Złe dane!</b></font>";
  else
  {
    Lc = Lu = 0; w = 1; u = false;
    for(i = 0; i < s1.length; i++)
      if(s1.charAt(i) == ',') u = true;
      else
      {
        c = s1.charCodeAt(i) - 48;
        if(c > 9) c -= 7;
        if(u)
        {
          Lu = p1 * Lu + c; w *= p1;
        }
        else Lc = p1 * Lc + c;
      }
    rLu = Lu / w; t = "";
    do
    {
      c = Lc % p2;
      if(c < 10) t = String.fromCharCode(c + 48) + t;
      else       t = String.fromCharCode(c + 55) + t;
      Lc = Math.floor(Lc / p2);
    } while(Lc);
    if(Lu)
    {
      t += ',';
      w = (15 * Math.log(10) / Math.log(p2)); // ograniczamy cyfry po przecinku 
      while((w > 0) && (t.length < 32))
      {
        w--;
        rLu *= p2;
        c = Math.floor(rLu);
        if(c < 10) t += String.fromCharCode(c + 48);
        else       t += String.fromCharCode(c + 55);
        rLu = rLu - c;
      }
      while(t.charAt(t.length-1) == '0') t = t.substring(0,t.length-1);
    }
    t = s1 + "<sub>(" + p1 + ")</sub> = " + t + "<sub>(" + p2 + ")</sub>";
  };
  document.getElementById("out_t").innerHTML = t;
}

</script>
    </div>
  </body>
</html>

 

Tutaj możesz przetestować działanie prezentowanego skryptu:

Przeliczanie liczb zapisanych
w różnych systemach pozycyjnych

(C)2005 mgr Jerzy Wałaszek   I LO w Tarnowie
Liczba wejściowa = Podstawa wejściowa 2...36 = 
Podstawa docelowa 2...36 = 

...

 

Zadania

Zadanie 1 (łatwe)

Oblicz wartości podanych poniżej liczb pozycyjnych:
A79A(11) =   

.

BA8B(12) =   

.

C6AB(13) =   

.

DFCA(16) =   

.

ZXVB(36) =   

.

 

Zadanie 2 (łatwe)

Przelicz liczbę dziesiętną o wartości 9999(10) kolejno na systemy pozycyjne. Cyfry dodatkowe wpisuj dużymi literkami.
9999(10) = (11)  

.

9999(10) = (12)  

.

9999(10) = (16)  

.

9999(10) = (20)  

.

9999(10) = (30)  

.

 

Zadanie 3 (łatwe)

Oblicz wartości podanych poniżej liczb stałoprzecinkowych. Wynik wpisz w postaci części całkowitej i ułamka właściwego, np. 276 2/37. Część całkowitą oddziel od ułamka dokładnie jedną spacją.
AA47,34A(11) =   

.

EEA,7BC(15) =   

.

DFFD,A45(16) =   

.

GHI7,HH8(22) =   

.

ZXM3,3KL(36) =   

.

 

Zadanie 4 (łatwe)

Przedstaw liczbę 2893,746(10) w systemie dwudziestkowym z dokładnością do 5 cyfr po przecinku.
2893,746(10) = (20)  

.

 

Podsumowanie

W praktyce spotykamy tylko jeden system pozycyjny o podstawie większej od 10 - system szesnastkowy. Jest on powszechnie stosowany do reprezentacji kodów binarnych z uwagi na prostotę konwersji szesnastkowo binarnej. Pozostałe systemy mają znaczenie tylko teoretyczne.

 


Zobacz dalej...

Wartość liczby pozycyjnej | Schemat Hornera | Przeliczenia na inny zapis pozycyjny | Wartość liczby stałoprzecinkowej | Przeliczanie na zapis stałoprzecinkowy | Zapis zmiennoprzecinkowy



List do administratora Serwisu Edukacyjnego Nauczycieli I LO

Twój email: (jeśli chcesz otrzymać odpowiedź)
Temat:
Uwaga: ← tutaj wpisz wyraz  ilo , inaczej list zostanie zignorowany

Poniżej wpisz swoje uwagi lub pytania dotyczące tego rozdziału (max. 2048 znaków).

Liczba znaków do wykorzystania: 2048

 

W związku z dużą liczbą listów do naszego serwisu edukacyjnego nie będziemy udzielać odpowiedzi na prośby rozwiązywania zadań, pisania programów zaliczeniowych, przesyłania materiałów czy też tłumaczenia zagadnień szeroko opisywanych w podręcznikach.



   I Liceum Ogólnokształcące   
im. Kazimierza Brodzińskiego
w Tarnowie

©2017 mgr Jerzy Wałaszek

Dokument ten rozpowszechniany jest zgodnie z zasadami licencji
GNU Free Documentation License.