Features reales reales, seu diligenter cum ipsa

Post publication vasa de notis typing in PostgreSQL, primus commentus erat de difficultatibus cum realibus numeris operandi. Cito inspicere decrevi codicem quaestionis SQL mihi praesto esse ut videam quoties genere reali utantur. Usu id saepe evenit, nec tincidunt semper pericula intellegam id. Et hoc non obstante quod in interreti et in Habre sunt satis multa bona vasa de formis numerorum in computatrali memoria ac de operando cum illis condiendis. Ideo in hoc articulo conabor huiusmodi lineamenta ad PostgreSQL applicare, et festinanter inspicere molestias cum illis associatas conabor, ut facilius SQL interrogationes tincidunt evitet.

Documenta PostgreSQL succincte asserit: "Procuratio talium errorum et earum propagationis in computatione subiectum est totius mathematici et scientiae computatricis, et hic non contegitur" (dum sapienter lectorem ad IEEE 754 regulam referens). Quales hic errores intelliguntur? Displiceamus ordine, mox patebit cur rursus calamum sustuli.

Sit pro exemplo simplex petitio;

********* Π—ΠΠŸΠ ΠžΠ‘ *********
SELECT 0.1::REAL;
**************************
float4
--------
    0.1
(1 строка)

Quam ob rem aliquid speciale non videbimus - expectata feres 0.1. Sed iam comparemus ad 0.1:

********* Π—ΠΠŸΠ ΠžΠ‘ *********
SELECT 0.1::REAL = 0.1;
**************************
?column?
----------
f
(1 строка)

Haud par! Quae miracula! Porro autem. Dicet aliquis, scio rem male facere cum fractionibus, quare integros ibi intrabo, et cum illis omnia certa erunt. Ok, mitte numerum 123 ad realem;

********* Π—ΠΠŸΠ ΠžΠ‘ *********
SELECT 123456789::REAL::INT;
**************************
   int4   
-----------
123456792
(1 строка)

Et contigit ut 3 more! Id est, tandem oblitus database numerare! An male aliquid facimus? Sit instar est.

Primum materielem meminerimus. Ut nostis, quilibet numerus decimalis in decem potestates ampliari potest. Erit ergo numerus 123.456 aequalis 1*102 + 2*101 + 3*100 + 4*10-1 + 5* 10-2 + ​​6*10-3. Sed computatrum in forma binaria numeris operatur, ergo in forma expansionis in duabus potentiis repraesentari debent. Numerus ergo 5.625 in binario repraesentatur ut 101.101, eritque = 1*22 + 0*21 + 1*20 + 1*2-1 + 0*2-2 + 1*2-3. Et si potentiae affirmativae duorum semper dant numeros integros decimales (1, 2, 4, 8, 16, etc.), tunc in negativis omnia sunt magis implicata (0.5, 0.25, 0.125, 0,0625, etc.). Quaestio est Non omnis decimalis repraesentari potest ut fractio binaria finita. Ita notum nostrum 0.1 in forma fractionis binariae apparet ut valor periodicus 0.0(0011). Quapropter valor finalis huius numeri in memoria computatrali secundum paulum profunditatem variabit.

Nunc tempus est meminisse quomodo numeri reales in memoria computatrali recondantur. Communiter numerus realis constat tribus partibus principalibus, signo, mantissa et exponente. Signum potest esse vel plus vel minus, ideo unum frenum datum est ei. Numerus autem frumentorum mantissae et exponentis per genuinum genus determinatur. In typo reali mantissa longitudo est 23 frusta (una frenum aequale 1 implicite additur initio mantissae, et effectus est 24), et exponens est 8 frusta. Summa est 32 frusta, seu 4 bytes. Et pro duplici praecisione, longitudo mantissa erit 52 frusta, et exponens erit 11 frusta, ad summam 64 bits, vel octo bytes. PostgreSQL accurationem superiorem numeri punctum nantis non adiuvat.

Numerum decimalem nostrum 0.1 in rationes tam reales quam duplices ACCURATIO stipant. Cum signum et valorem exponentis idem sint, mantissa intendunt (delibero omitto notas non-obvias recondere valores exponentis ac valores nullius reales, cum intellectum implicant et ab essentia distrahunt. quaestionis, si interest, vide IEEE 754 vexillum). Quid dabimus? In linea suprema mantissam dabo pro typo reali (inspecta rotunditate ultimi per 1 ad numerum repraesentabilem proxime, alioquin erit 0.099999...), et in linea ima - nam DUPLEX genus ACCURATIO:

0.000110011001100110011001101
0.00011001100110011001100110011001100110011001100110011001

Hi sane sunt duo numeri omnino diversi! Comparando igitur primus numerus cyphris additus erit, ac proinde major quam secundus (obtentu rotunditatis - notatum in audax). Id e nostris exemplis explicat ambiguum. In secundo exemplo, numerus expresse definitus 0.1 ad typum duplicem ACCURATIO proicitur, ac deinde cum numero reali comparatur. Utrumque ad idem genus reducuntur, nosque ad id ipsum quod supra vidimus. Quaesitum modificemus ut omnia in locum cadant;

********* Π—ΠΠŸΠ ΠžΠ‘ *********
SELECT 0.1::REAL > 0.1::DOUBLE PRECISION;
**************************
?column?
----------
t
(1 строка)

Et quidem, duplicem reductionem numeri 0.1 ad realem et duplicem praecisionem faciendo, responsio ad problema pervenitur:

********* Π—ΠΠŸΠ ΠžΠ‘ *********
SELECT 0.1::REAL::DOUBLE PRECISION;
**************************

      float8       
-------------------
0.100000001490116
(1 строка)

Hoc etiam ex- plicat tertium exemplum supra. Numerus simplex 123 est impossibile est ut fit in mantissa in XXIV bits (23 explicit + 1 implied). Maximus integer, qui in 24 minutas aptari potest, est 224-1 = 16, 777. Ergo numerus noster 215 rotundus est ad proximum repraesentabile 123, 456, 789. Mutato genere ad DUPLEX ACCURATIO, hanc missionem amplius non videmus;

********* Π—ΠΠŸΠ ΠžΠ‘ *********
SELECT 123456789::DOUBLE PRECISION::INT;
**************************
   int4   
-----------
123456789
(1 строка)

Id omne. Vertit nulla miracula. Sed omnia quae descripta sunt, iusta ratio est cogitare quantum vere postulo reale genus. Maxima fortasse utilitas eius usus est celeritas calculi cum nota accurationis iactura. Sed nunquid hoc esset missionis universalis quae tam frequentem huius generis usum iustificaret? Nolite arbitrari.

Source: www.habr.com