Post publication
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