Salut à tous.
Je suis sous Windows 10 Pro et j'utilise FireBird version 4.0.2.
Dans la documentation officielle de FireBird, il est dit que "Decimal" et "Numeric" sont synonymes.
--> Documentation FireBird 4.0.
Il y a une erreur dans la documentation puisqu'il est dit que le type decimal peut être sur 16 bits.
C'est faux ! Seul le type Numeric peut être sur 16 bits.
Dans mon test ci-après, j'ai chercher la limite qui permet de stocker le plus grand nombre soit en decimal soit en numeric.
J'ai aussi fait varier la mantisse, mais je n'ai pas touché à l'exposant qui dans mon exemple est à 2.
La mantisse est la plus grande valeur possible avant le changement dans le stockage de la valeur.
Voici mon test :
Comme on peut le constater, la première valeur passe tandis que la seconde est rejeté, soit sous "out of range" ou soit sous "overflow".Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114 CREATE TABLE TEST (val numeric(4,2)); INSERT INTO TEST (val) VALUES (327.67); INSERT INTO TEST (val) VALUES (327.68); Statement failed, SQLSTATE = 22003 arithmetic exception, numeric overflow, or string truncation -numeric value is out of range After line 2 in file Base.sql SELECT * FROM TEST; VAL ======= 327.67 COMMIT; RECREATE TABLE TEST (val numeric(9,2)); INSERT INTO TEST (val) VALUES (21474836.47); INSERT INTO TEST (val) VALUES (21474836.48); Statement failed, SQLSTATE = 22003 arithmetic exception, numeric overflow, or string truncation -numeric value is out of range After line 9 in file Base.sql SELECT * FROM TEST; VAL ============ 21474836.47 COMMIT; RECREATE TABLE TEST (val numeric(18,2)); INSERT INTO TEST (val) VALUES (92233720368547758.07); INSERT INTO TEST (val) VALUES (92233720368547758.08); Statement failed, SQLSTATE = 22003 arithmetic exception, numeric overflow, or string truncation -Integer overflow. The result of an integer operation caused the most significant bit of the result to carry. After line 16 in file Base.sql SELECT * FROM TEST; VAL ===================== 92233720368547758.07 COMMIT; commit; RECREATE TABLE TEST (val numeric(36,2)); INSERT INTO TEST (val) VALUES (1701411834604692317316873037158841057.27); INSERT INTO TEST (val) VALUES (1701411834604692317316873037158841057.28); Statement failed, SQLSTATE = 22003 arithmetic exception, numeric overflow, or string truncation -numeric value is out of range After line 24 in file Base.sql SELECT * FROM TEST; VAL ============================================= 1701411834604692317316873037158841057.27 COMMIT; RECREATE TABLE TEST (val decimal(9,2)); INSERT INTO TEST (val) VALUES (21474836.47); INSERT INTO TEST (val) VALUES (21474836.48); Statement failed, SQLSTATE = 22003 arithmetic exception, numeric overflow, or string truncation -numeric value is out of range After line 31 in file Base.sql SELECT * FROM TEST; VAL ============ 21474836.47 COMMIT; RECREATE TABLE TEST (val decimal(18,2)); INSERT INTO TEST (val) VALUES (92233720368547758.07); INSERT INTO TEST (val) VALUES (92233720368547758.08); Statement failed, SQLSTATE = 22003 arithmetic exception, numeric overflow, or string truncation -Integer overflow. The result of an integer operation caused the most significant bit of the result to carry. After line 38 in file Base.sql SELECT * FROM TEST; VAL ===================== 92233720368547758.07 commit; RECREATE TABLE TEST (val decimal(36,2)); INSERT INTO TEST (val) VALUES (1701411834604692317316873037158841057.27); INSERT INTO TEST (val) VALUES (1701411834604692317316873037158841057.28); Statement failed, SQLSTATE = 22003 arithmetic exception, numeric overflow, or string truncation -numeric value is out of range After line 45 in file Base.sql SELECT * FROM TEST; VAL ============================================= 1701411834604692317316873037158841057.27 exit; Appuyez sur une touche pour continuer...
Je tiens à mettre au point la méconnaissance que certains ont à ce sujet, de ce que j'ai pu lire dans ce forum.
Je ne citerai pas les noms, ils se reconnaitrons certainement d'eux même.
a) le decimal et le numeric sont stockés en entiers binaires ! Il y a le choix entre quatre types :
--> Smallint : 16 bits
--> Integer : 32 bits
--> Bigint : 64 bits
--> Int128 : 128 bits
P.S.: Int128 est un nouveau type qui est apparu dans la version FireBird 4.0.
b) Le premier nombre dans la déclaration du type Decimal ou Numeric se nomme mantisse.
Ce nombre ne sert pas à limiter le nombre de chiffres à l'affichage, mais à déterminer le type de stockage.
Le deuxième nombre se nomme l'exposant. Il sert à positionner la virgule fixe dans le nombre stockée.
Dans le cas de la déclaration "Decimal(36,2)", 36 est la mantisse et 2 est l'exposant.
Dans le nombre +2127 - 1, j'ai au total 39 chiffres alors que la mantisse indique 36 seulement.
Le fait de donner 36 comme mantisse, va automatiquement attribuer le type Int128 pour le stockage.
L'exposant est 2. En lisant la mantisse par la droite, on place la virgule fixe à gauche du deuxième chiffres.
c) Il ne s'agit pas d'une représentation DCB (decimal codé binaire) comme j'ai pu le lire.
Pour rappel, en DCB, un chiffre décimal est stocké dans un quartet, c'est-à-dire sur quatre bits.
Les N chiffres seront stockés sur N * 4 bits. Pour un nombre de 36 chiffres, il faut 36 * 4 = 144 bits soit 18 octets.
Avec la représentation binaire, il suffit de 16 octets au maximum pour stocker nos 36 chiffres décimaux
De ce fait, on gagne deux octets, ce qui n'est pas négligeable dans une base de données de plusieurs millions de lignes.
En Cobol, le DCB est utilisé dans le type packed decimal qui utilise la clause COMP-3.
A ma connaissance, il n'y a pas de représentation DCB dans FireBird.
d) Pour les limites, nous trouvons :
--> 2 15 = 32 768
--> 2 31 = 2 147 483 648
--> 2 63 = 9 223 372 036 854 775 808
--> 2127 = 170 141 183 460 469 231 731 687 303 715 884 105 728
Pourquoi cette limite ? Parce que l'on stocke des nombres signés.
e) Voici le résumé du type Numeric :
f) Et voici le résumé du type Decimal :Code:
1
2
3
4
5 +---------+--------------------+-------------------+------------------+-------------------+ | Type | Range 1 to 4 | Range 5 to 9 | Range 10 to 18 | Range 19 to 36 | +---------+--------------------+-------------------+------------------+-------------------+ | Numeric | Smallint (16 bits) | Integer (32 bits) | Bigint (64 bits) | int128 (128 bits) | +---------+--------------------+-------------------+------------------+-------------------+
e) Après quelques recherches, il s'agit d'une retro compatibilité avec d'anciennes version d'InterBase, v.5 et inférieures.Code:
1
2
3
4
5 +---------+-------------------+------------------+-------------------+ | Type | Range 1 to 9 | Range 10 to 18 | Range 19 to 36 | +---------+-------------------+------------------+-------------------+ | Decimal | Integer (32 bits) | Bigint (64 bits) | int128 (128 bits) | +---------+-------------------+------------------+-------------------+
Pour le dialect=1, le stockage d'un nombre décimal fixe supérieur à 9 chiffres se faisaient dans du flottant.
Je suppose que par flottant, il s'agit de float ou de double.
Pour le dialect=3, cela se fait maintenant dans du fixe. D'après mes tests, il s'agit bien d'entiers binaires.
f) Il n'y a pas de problèmes d'arrondis car c'est du binaire et non du float ou double.
Le flottant est réservé aux calculs scientifiques et non au financier.
Cordialement.
Artemus24.
@+